... ...

JAXB and XML without namespace

There is XML provided by suppliers:

<?xml version="1.0" encoding="utf-8"?> <Foo> <Bar>...</Bar> <Bar>...</Bar> </Foo> 

Note that there is no xmlns="..." declaration, and the provider does not provide a schema. This cannot be changed, and in the future, the provider will continue to send XML this way.

To generate JAXB bindings, I created a circuit like this:

 <?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://acme.com/schema" xmlns:tns="http://acme.com/schema" elementFormDefault="qualified"> <xsd:element name="Foo"> <xsd:complexType> <xsd:sequence> <xsd:element ref="tns:Bar" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="Bar"> ... </xsd:element> </xsd:schema> 

Note that I have declared a more or less meaningful namespace (" http://acme.com/schema ") so that it can be used to refer to elements, etc. XJC generates the following package-info.java :

 @javax.xml.bind.annotation.XmlSchema(namespace = "http://acme.com/schema", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package com.acme.schema; 

Then I try to untie the XML document:

 JAXBContext jaxb = JAXBContext.newInstance("com.acme.schema"); Unmarshaller unmarshaller = jaxb.createUnmarshaller(); InputStream is = this.getClass().getClassLoader().getResourceAsStream("test.xml"); InputSource source = new InputSource(is); Foo foo = (Foo) unmarshaller.unmarshal(source); 

Here is the exception I get:

 javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"Foo"). Expected elements are <{http://acme.com/schema}Foo>,...> 

Obviously, this is because the XML elements belong to the empty namespace and the JAXB classes are non-empty.

Is there a way to fake the XML namespace (perhaps during XML parsing) so that JAXB recognizes the elements and successfully binds them? SAX / StAX solutions are preferred over the DOM because XML documents can be quite large.

+5
source share
1 answer

First off, I would not recommend all of this. Integration with a third-party API is quite complicated, without adding additional complications. Why add a namespace at all? I'm not sure that you will come out of this. Think of the lucky one who inherits your code base. They will see the addition of a namespace, but they have no idea why you are doing this.

I would take it one step further and suggest completely eliminating the scheme and just using annotated POJOs. All these steps just add complications, build steps, etc.

However, if you decide, this is similar to the quintessence for XSL transformations. You can find an XSL transform that adds namespaces quite easily, like this question . This is an easy way to connect your conversion to JAXB ...

 private static Foo unmarshalDocument(InputStream xslStream, InputStream xmlStream) throws Exception { StreamSource stylesource = new StreamSource(xslStream); StreamSource inputStream = new StreamSource(xmlStream); Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource); JAXBResult result = new JAXBResult(context); transformer.transform(inputStream, result); return (Foo) result.getResult(); } 
+2
source

All Articles