user1452030
user1452030

Reputation: 1021

JAXB Unmarshalling issues when wrapper element and root element are the same

I have an XML with the following structure:

<?xml version="1.0" encoding="UTF-8"?>
<catalog_titles xmlns="http://www.company.com/catalog3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.company.com/catalog3 catalog3.xsd" version="1.0" created="2017-04-26T07:31:12.443Z" language="en" country="xx">
  <catalog_title id="80153288" type="product1">
    ... Catalog specific fields ...
  </catalog_title>
  <catalog_title id="2" type="product2">
  </catalog_title">
</catalog_titles>

I have the following mapping classes:

CatalogFeed.java

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="catalog_titles")
public class CatalogFeed extends Model {
    @XmlElement(name="catalog_title")
    List<CatalogTitle> catalogTitles;
}

CatalogTitle.java

@XmlAccessorType(XmlAccessType.FIELD)
public class CatalogTitle extends Model {
    @XmlAttribute(name="id")
    private int id;
    ... Other fields with similar mappings
}

When I try parsing using this setup (the unmarshalling class is generic and it works fine for several other files and the Model class is pretty basic and only has convenience methods like over-ridden toString that prints a JSON version of the object. Nothing XML related), I'm getting the following exception:

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.company.com/catalog3", local:"catalog_titles"). Expected elements are <{}catalog_titles>
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1131)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:556)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3132)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:852)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
at com.mycompany.ingestion.importer.parser.GenericParser.parse(GenericParser.java:19)
at com.mycompany.ingestion.importer.Importer.lambda$0(Importer.java:64)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at com.mycompany.ingestion.importer.Importer.loadFeedData(Importer.java:62)
at com.mycompany.ingestion.importer.Importer.run(Importer.java:43)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:732)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:716)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:703)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:304)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at com.mycompany.ingestion.importer.ImporterApplication.main(ImporterApplication.java:10)

Interestingly, if I remove all the attributes of catalog_titles and just leave it as , the parser works fine.

I have no control over the XML structure and I'd like to avoid pre-processing and manipulating the original feed file, if possible. Is there a better way to annotate my classes to avoid the exception?

P.S: I'm not auto-generating my classes and they are all hand-typed based on the XML fields.

Upvotes: 0

Views: 665

Answers (1)

teppic
teppic

Reputation: 7286

You need to define the namespaces for your element models:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(namespace = "http://www.company.com/catalog3", name = "catalog_titles")
public static class CatalogFeed {
    @XmlElement(namespace = "http://www.company.com/catalog3", name = "catalog_title")
    List<CatalogTitle> catalogTitles;
}

Upvotes: 1

Related Questions