JAXB unmarshal with declared type does not populate the resulting object with data

10,402

Your XML document does not match the namespace qualification that was defined in your mappings (see: http://blog.bdoughan.com/2010/08/jaxb-namespaces.html). You could leverage an XMLFilter to apply a namespace to your XML document during the unmarshal operation.

import org.xml.sax.*;
import org.xml.sax.helpers.XMLFilterImpl;

public class NamespaceFilter extends XMLFilterImpl {

    private static final String NAMESPACE = "htp://www.example.com/mdf/v4";

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        super.endElement(NAMESPACE, localName, qName);
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        super.startElement(NAMESPACE, localName, qName, atts);
    }

}

Below is an example of how you would leverage the XMLFilter during an unmarshal.

    // Create the XMLFilter
    XMLFilter filter = new NamespaceFilter();

    // Set the parent XMLReader on the XMLFilter
    SAXParserFactory spf = SAXParserFactory.newInstance();
    SAXParser sp = spf.newSAXParser();
    XMLReader xr = sp.getXMLReader();
    filter.setParent(xr);

    // Set UnmarshallerHandler as ContentHandler on XMLFilter
    Unmarshaller unmarshaller = jc.createUnmarshaller();
    UnmarshallerHandler unmarshallerHandler = unmarshaller
            .getUnmarshallerHandler();
    filter.setContentHandler(unmarshallerHandler);

    // Parse the XML
    InputSource xml = new InputSource("input.xml");
    filter.parse(xml);
    Object result = unmarshallerHandler.getResult();

For More Information

Share:
10,402
Slacky
Author by

Slacky

Updated on June 05, 2022

Comments

  • Slacky
    Slacky almost 2 years

    I am trying to unmarshal a given XML:

    <FHcomment>
     <TX>rewriting of file</TX>
     <tool_id>toolA</tool_id>
     <tool_vendor>Company</tool_vendor>
     <tool_version>1.7.36.0</tool_version>
    </FHcomment>
    

    The schema has already been compiled to JAXB classes, see here:

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
     "tx",
     "toolId",
     "toolVendor",
     "toolVersion",
     "userName",
     "commonProperties",
     "extensions"
    })
    @XmlRootElement(name = "FHcomment")
    public class FHcomment {
    
    @XmlElement(name = "TX", required = true)
    protected TX tx;
    @XmlElement(name = "tool_id", required = true)
    protected BaseName toolId;
    @XmlElement(name = "tool_vendor", required = true)
    protected BaseName toolVendor;
    @XmlElement(name = "tool_version", required = true)
    protected BaseVersion toolVersion;
    @XmlElement(name = "user_name")
    protected BaseName userName;
    @XmlElement(name = "common_properties")
    protected CommonPropertiesType commonProperties;
    protected ExtensionsType extensions;
    @XmlAnyAttribute
    private Map<QName, String> otherAttributes = new HashMap<QName, String>();
    
    .....
    /*
     * GETTERS and SETTERS for the fields have been removed here
     */
    .....
    }
    

    My code to unmarshal the XML is as follows:

    JAXBContext jc = JAXBContext.newInstance(FHcomment.class);
    String s = "<FHcomment>....</Fhcomment>";
    Unmarshaller unmarshaller = jc.createUnmarshaller();
    XMLInputFactory fac = XMLInputFactory.newFactory();
    XMLStreamReader xsr = fac.createXMLStreamReader(new StringReader(s));
    JAXBElement<FHcomment> foo = unmarshaller.unmarshal(xsr, FHcomment.class);
    FHcomment val = foo.getValue();
    

    Problem: The resulting FHcomment object does not contain the children elements of FHcomment. All are null which is not the desired result.

    How can I tell JAXB to completely unmarshal the given XML into an object?

    EDIT: After adding a ValidationHandler to the Unmsarshaller, I got closer to the problem:

    unexpected element (uri:"", local:"TX"). Expected elements are <{htp://www.example.com/mdf/v4}tool_id>,<{htp://www.example.com/mdf/v4}TX>,<{htp://www.www.example.com/mdf/v4}common_properties>,<{htp://www.example.com/mdf/v4}tool_version>,<{htp://www.example.com/mdf/v4}extensions>,<{htp://www.www.example.com/mdf/v4}tool_vendor>,<{htp://www.www.example.com/mdf/v4}user_name>

    unexpected element (uri:"", local:"tool_id"). Expected elements are....

    It turns out JAXB does not like the fact that the provided XML does not contain namespace information.. So how do I tell the unmarshaller to ignore the namespaces?

    EDIT2:

    After some more research I could not find a way to trick JAXB into working without namespace verification. I used the tutorial at http://cooljavablogs.blogspot.de/2008/08/how-to-instruct-jaxb-to-ignore.html to circumvent my problem. Not a nice solution but the best at hand...

  • Slacky
    Slacky almost 11 years
    Sadly the classes are generated and any modification will be lost after an update to the schema definitions.
  • Balint Bako
    Balint Bako almost 11 years
    Then update the xml... You need make BaseName and TX xml-serializable too, by the way. If you use a custom class as a property in a JAXB class, that is a "complex type" in the XSD.