Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB XML unmarshalling only sees the root element

I have a problem unmarshalling a rather simple XML-document to plain Java objects.

This is what my XML looks like:

<?xml version="1.0" encoding="UTF-8"?>
<codeSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:hl7-org:v3 vocab.xsd" xmlns="urn:hl7-org:v3">
     <name>RoleCode</name>
     <desc>Codes voor rollen</desc>
     <code code="SON" codeSystem="2.16.840.1.113883.5.111" displayName="natural sonSon ">
         <originalText>The player of the role is a male offspring of the scoping entity (parent).</originalText>
     </code>
     <code code="DAUC" codeSystem="2.16.840.1.113883.5.111" displayName="Daughter">
           <originalText> The player of the role is a female child (of any type) of scoping entity (parent) </originalText>
     </code>
</codeSystem>

It's part of a much bigger file, a specification of the Hl7v3 code system for representing relationships between persons.

I created two Java classes for the CodeSystem and Code elements:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class CodeSystem
{
    private String name;

    private String desc;

    @XmlElement(name = "code")
    private List<Code> codes;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType
public class Code
{
    @XmlAttribute
    private String code;

    @XmlAttribute
    private String codeSystem;

    @XmlAttribute
    private String displayName;

    private String originalText;
}

I added a package-info.java containing:

@XmlSchema(
    namespace = "urn:hl7-org:v3",  
    elementFormDefault = XmlNsForm.UNQUALIFIED, 
    attributeFormDefault = XmlNsForm.UNQUALIFIED,
    xmlns = { 
        @javax.xml.bind.annotation.XmlNs(prefix = "", namespaceURI = "urn:hl7-org:v3") 
    }
)
package nl.topicuszorg.hl7v3.vocab2enum.model;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

Unmarshalling is pretty straightforward:

JAXBContext context = JAXBContext.newInstance(CodeSystem.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
CodeSystem codeSystem = (CodeSystem) unmarshaller.unmarshal(new File(args[0]));

This however results in an empty CodeSystem object. Nothing except the root element is parsed from the XML.

I can't figure out why the name, desc and code elements aren't recognized. Do they reside in a different namespace then the root element? They shouldn't be, because the namespace declaration in the root element is unprefixed.

What am I missing?

like image 277
Rens Verhage Avatar asked Jan 15 '23 12:01

Rens Verhage


1 Answers

In your XML document you have specified a default namespace. This means that any non-prefixed element is going to be in that namespace. In the fragment below both the codeSystem and name elements are qualified with the urn:hl7-org:v3 namespace.

<codeSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:hl7-org:v3 vocab.xsd" xmlns="urn:hl7-org:v3">
     <name>RoleCode</name>
     ...
</codeSystem>

You just need to change the elementFormDefault property on the @XmlSchema annotation to XmlNsForm.QUALIFIED. You currently have it as XmlNsForm.UNQUALIFIED which means that only global elements will be namespace qualified (the one corresponding to @XmlRootElement in your use case.

@XmlSchema(
    namespace = "urn:hl7-org:v3",  
    elementFormDefault = XmlNsForm.QUALIFIED, 
    attributeFormDefault = XmlNsForm.UNQUALIFIED,
    xmlns = { 
        @javax.xml.bind.annotation.XmlNs(prefix = "", namespaceURI = "urn:hl7-org:v3") 
    }
)
package nl.topicuszorg.hl7v3.vocab2enum.model;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

For More Information

  • http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
like image 168
bdoughan Avatar answered Jan 17 '23 16:01

bdoughan