XML namespace parsing

Issue #137 closed
Nathan Bruning 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">

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">

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. Christian Schudt repo owner

    Do you have a piece of code for reproduction? Afaik xsi:type is only is only required in the XSD, but not in the XML, so maybe the solution is to omit it.

  2. Nathan Bruning 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.

  3. Nathan Bruning 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"
        <xs:element name="myElement" type="parentType">
        <xs:complexType name="parentType">
        <xs:complexType name="childType">
                <xs:extension base="parentType">
                        <xs:element name="prop" type="xs:string"/>

    And this code:

            Writer writer = new StringWriter();
            XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newFactory().createXMLStreamWriter(writer);
            XMLStreamWriter xmppStreamWriter = XmppUtils.createXmppStreamWriter(
            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);

    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">
  4. Nathan Bruning reporter

    It's generated by XJC. Just a POJO class, extending ParentType, having one field (prop), a getter and a setter.

  5. 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.

  6. Log in to comment