views:

53

answers:

2

A simple task: write an element two attributes:

String nsURI = "http://example.com/";
XMLOutputFactory outF = XMLOutputFactory.newFactory();
outF.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
XMLStreamWriter out = outF.createXMLStreamWriter(System.out);
out.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, "element", nsURI);
out.writeAttribute("attribute", "value");
out.writeAttribute("attribute2", "value");
out.writeEndElement();
out.close();

Woodstox's answer:

<element xmlns="http://example.com/" attribute="value" attribute2="value"></element>

JDK 6 answer:

<zdef-1905523464:element xmlns="" xmlns:zdef-1905523464="http://example.com/" attribute="value" attribute2="value"></zdef-1905523464:element>

What?!

Further, if we add a prefix to the element:

out.writeStartElement("ns", "element", nsURI);

JDK 6 no longer attempts to emit xmlns="":

<ns:element xmlns:ns="http://example.com/" attribute="value" attribute2="value"></ns:element>

And if we drop an attribute (i.e. only have one) it's fine.

I'm fairly sure this is a bug in JDK 6. Am I right? And could anyone suggest a work around that will keep both libraries (and any others) happy? I don't want to require woodstox if I can help it.

A: 

I think you must tell the XMLStreamWriter what is the default namespace, and then use it when adding elements:

String nsURI = "http://example.com/";
XMLOutputFactory outF = XMLOutputFactory.newFactory();
outF.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
XMLStreamWriter out = outF.createXMLStreamWriter(System.out);
out.setDefaultNamespace(nsURI);
out.writeStartElement(nsURI, "element");
out.writeAttribute("attribute", "value");
out.writeAttribute("attribute2", "value");
out.writeEndElement();
out.close();

The above code gives me this output:

<element xmlns="http://example.com/" 
    attribute="value" attribute2="value"></element>

with java version "1.6.0_20"

MarcoS
Did you get the broken output before? This doesn't fix the problem for me in 1.6.0_18.
Or 1.6.0_20 which I just downloaded.
yes, I get the broken output using your original code
MarcoS
Ah, correction. Your code does work, but it's not just the default namespace that make the difference but using writeStartElement(nsURI, localname) instead of writeStartElement("", localname, nsURI). Thanks!
oh yes, sorry, perhaps my answer was not very clear, but that's what I meant.
MarcoS
A: 

My suggestion would be to never rely on 2-argument version of writeAttribute(), since definition of what exactly it ought to output is not clear: should it use namespace "" (aka "no namespace") or whatever is the current default namespace? This is especially confusing since as per XML specification, attributes never use the default namespace (only explicit ones). So arguably all behaviors expressed can be seen as potentially correct; but obviously they can not all be. It's just Stax API does not properly define (AFAIK) what the real answer should be (which sucks).

So: just specify namespace that attribute should use ("" or null both work for "no namespace") and things should work better.

Problem with JDK version, as far as I know, is that some versions assumed that attributes did in fact use the default namespace; and that's why that bogus 'xmlns=""' was added. It is unnecessary.

StaxMan