XML namespace parsing
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)
-
repo owner -
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.
-
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>
-
repo owner What about the most interesting part here, the
ChildType
class? -
reporter It's generated by XJC. Just a POJO class, extending
ParentType
, having one field (prop
), a getter and a setter. -
repo owner - changed status to resolved
-
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.
-
reporter Thanks, this indeed solves my issues. When are you planning to release this?
-
repo owner - changed status to closed
Fix version 0.8.0
- Log in to comment
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.