XML namespace parsing

Issue #137 closed
Nathan
created an issue

We are using a custom XSD schema with a namespace to define our own XMPP extension.

JAXB is correctly adding xsi:type attributes where necessary:

<ns2:iq xmlns:ns4="urn:ietf:params:xml:ns:xmpp-stanzas" xmlns:ns3="http://mynamespace" xmlns:ns2="jabber:client" id="..." to="romeo@example.net" type="set">
   <ns3:notification xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:queueUpdateNotification">
      ...
   </ns3:notification>
</ns2:iq>

But when Babbler pushes the XML through the PrefixFreeCanonicalizationWriter, it results in:

<iq id="..." to="romeo@example.net" type="set">
   <notification xmlns="http://mynamespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:queueUpdateNotification">
      ...
   </notification>
</iq>

Note that the resulting XML contains a "ns3" prefix which is unbound. Actually, when the same XML is later received by Babblet, a parser error is thrown.

I guess the root cause if that xsi:type is a QName but writeAttribute of the PrefixFreeCanonicalizationWriter does no rewrite attributes.

Any suggestions?

Comments (9)

  1. Nathan reporter

    I'll see if I can come up with a minimal reproduction scenario.

    The xsi:type is definately required in the generated XML, as it's the only way for a parser to determine the actual type of an element when subtyping (polymorphism) is used in XSD.

  2. Nathan reporter

    Given this XSD:

    <xs:schema targetNamespace="http://testnamespace.com"
               xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
               xmlns="http://testnamespace.com" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
               jxb:version="1.0">
        <xs:element name="myElement" type="parentType">
        </xs:element>
    
        <xs:complexType name="parentType">
        </xs:complexType>
    
        <xs:complexType name="childType">
            <xs:complexContent>
                <xs:extension base="parentType">
                    <xs:sequence>
                        <xs:element name="prop" type="xs:string"/>
                    </xs:sequence>
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
    
    </xs:schema>
    

    And this code:

            Writer writer = new StringWriter();
            XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newFactory().createXMLStreamWriter(writer);
            XMLStreamWriter xmppStreamWriter = XmppUtils.createXmppStreamWriter(
                    xmlStreamWriter,
                    "jabber:client",
                    true);
    
            JAXBContext jaxbContext = JAXBContext.newInstance(ClientIQ.class, ObjectFactory.class);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
    
            ObjectFactory factory = new ObjectFactory();
            JAXBElement<ParentType> childElem = factory.createMyElement(new ChildType());
    
            IQ iq = new IQ(Jid.of("romeo@example.net"), IQ.Type.SET, childElem);
            marshaller.marshal(ClientIQ.from(iq), xmppStreamWriter);
            xmppStreamWriter.flush();
            System.out.println(writer.toString());
    

    Results in the following (incorrect) XML:

    <iq id="6549cbb8-d2e4-4018-8b99-f29e9305eef4" to="romeo@example.net" type="set">
        <myElement xmlns="http://testnamespace.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:childType">
        </myElement>
    </iq>
    
  3. Christian Schudt repo owner

    I've hopefully fixed this issue. If an "xsi:type" is written with a "prefix:namespace", it ensures, that there's also a "xmlns:prefix="namespace" somewhere. Unless the namespace is already the default namespace.

  4. Log in to comment