Multi-Namespace XML Document with no prefixes

907 views Asked by At

I have an interesting situation where my XML editor (Oxygen, which uses Xerces XML processor) requires a prefix on the root tag, but my JAXB XML Marshaller (also Xercies-based) requires no prefix on the root tag. I'm trying to understand this situation.

First the 2 schema files:

ns1.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.ns1.com"
    xmlns="http://www.ns1.com"
    xmlns:ns2="http://www.ns2.com"
    elementFormDefault="unqualified"
    attributeFormDefault="unqualified"
    version="1.0" >
    <xs:import namespace="http://www.ns2.com" schemaLocation="ns2.xsd"/>
    <xs:element name="root"> 
        <xs:complexType>
            <xs:all>
                <xs:element name="element1">
                    <xs:complexType>
                        <xs:all> 
                            <xs:element name="element1a" type="NS1Type"/>
                            <xs:element name="element1b" type="ns2:NS2Type"/>
                        </xs:all>
                    </xs:complexType>
                </xs:element>
            </xs:all>
        </xs:complexType>
    </xs:element>
    <xs:simpleType name="NS1Type">
        <xs:restriction base="xs:string">
            <xs:enumeration value="VALUE_1"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

ns2.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.ns2.com"
    xmlns="http://www.ns2.com"
    elementFormDefault="unqualified"
    attributeFormDefault="unqualified"
    version="1.0" >

    <xs:complexType name="NS2Type">
        <xs:all>
            <xs:element name="value" type="xs:float" minOccurs="0"/>
        </xs:all>
    </xs:complexType>
</xs:schema>

What the current release of Oxygen (16.1) requires what I'm going to call "Version 1"

Version 1

<?xml version="1.0" encoding="UTF-8"?>
<ns1:root 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:ns1="http://www.ns1.com"
 xsi:schemaLocation="http://www.ns1.com ../schema/ns1.xsd">
    <element1>
        <element1a>VALUE_1</element1a>
        <element1b>
            <value>4.5</value>
        </element1b>
    </element1>
</ns1:root>

If instead I remove the prefix like this example (Version 1):

Version 2

<?xml version="1.0" encoding="UTF-8"?>
<root 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:ns1="http://www.ns1.com"
 xsi:schemaLocation="http://www.ns1.com ../schema/ns1.xsd">
    <element1>
        <element1a>VALUE_1</element1a>
        <element1b>
            <value>4.5</value>
        </element1b>
    </element1>
</root>

Oxygen complains:

"[Xerces] cvc-elt.1.a: Cannot find the declaration of element 'root'."

JAXB on the other hands will only except Version 2. If I supply Version 1, I get this error:

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

The full stacktrace is:

at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:662)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:253)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:120)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1063)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:498)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:480)
    at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:150)
    at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.DTDConfiguration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)

Right now the JAXB marshaller and unmarshaller code is:

    JAXBContext context = JAXBContext.newInstance(object.getClass());
    javax.xml.bind.Marshaller marshaller = context.createMarshaller();


    JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

Though I will soon be allowing Swagger Core to do the marshalling and unmarshalling and Swagger uses Jackson XML.

I need to figure out how to construct this XML (or configure JAXB) in a way that both my editor and my JAXB unmarshaller accept it

1

There are 1 answers

0
lexicore On BEST ANSWER

The problem is not prefixes but namespaces.

Your schemas have target namespaces but also elementFormDefault="unqualified" (are you sure you want this?). This means that global elements are qualified but local elements are not.

So your root element is qualified and belongs to the namespace http://www.ns1.com. So the Xerces error message is correct.

The other question is, why does JAXB not recognize the namespace. A you did not post your Java code (please do) I have two theories:

  • You have defined JAXB annotations manually but did not define the namespace correctly.
  • You have generated your code using XJC or something based on that but somehow miss package-info.java which usually defines the prefix.

By the way I would not call any JAXB implementation "Xerces-based".