How to marshal without a namespace?
The following did the trick for me:
XMLStreamWriter writer = ...
writer.setNamespaceContext(new NamespaceContext() {
public Iterator getPrefixes(String namespaceURI) {
return null;
}
public String getPrefix(String namespaceURI) {
return "";
}
public String getNamespaceURI(String prefix) {
return null;
}
});
Check your package-info.java
(in the package where your jaxb-annotated classes are). There is the namespace
attribute of @XmlSchema
there.
Also, there is a namespace
attribute in the @XmlRootElement
annotation.
I've tried all solutions provided as answers here and none of them worked for my environment. My current requirements are:
- jdk1.6.0_45
- JAXB annotated classes are generated upon every rebuild, so changing them is not an option.
I'd like to share with you the results my experiments with solutions I've found on stackoverflow.
Custom NamespaceContext link
Simple and elegant solution, but in my environment I have an exception with the following stacktrace:
javax.xml.stream.XMLStreamException: Trying to write END_DOCUMENT when document has no root (ie. trying to output empty document).
at com.ctc.wstx.sw.BaseStreamWriter.throwOutputError(BaseStreamWriter.java:1473)
at com.ctc.wstx.sw.BaseStreamWriter.reportNwfStructure(BaseStreamWriter.java:1502)
at com.ctc.wstx.sw.BaseStreamWriter.finishDocument(BaseStreamWriter.java:1663)
at com.ctc.wstx.sw.BaseStreamWriter.close(BaseStreamWriter.java:288)
at MyDataConverter.marshal(MyDataConverter.java:53)
I got stuck trying to figure out why this exception occurs and decided to try out something else.
Modification of package-info.java link
The simplest solution I've found. It generally works, but this file is generated upon every build. That's why I have to find another solution.
Schema modification link
Works as described but doesn't solve my problem. I still have a namespace in root element.
DelegatingXMLStreamWriter link
I've also tried solutions mentioned there, but I had a strange assertion in com.sun.xml.bind.v2.runtime.output.NamespaceContextImpl (method declareNsUri) which I've failed to defeat.
My solution
While researching the issue with assertion I had to implement my own version of XMLStreamWriter based on DelegatingXMLStreamWriter.java
public class NamespaceStrippingXMLStreamWriter extends DelegatingXMLStreamWriter {
public NamespaceStrippingXMLStreamWriter(XMLStreamWriter xmlWriter) throws XMLStreamException {
super(xmlWriter);
}
@Override
public void writeNamespace(String prefix, String uri) throws XMLStreamException {
// intentionally doing nothing
}
@Override
public void writeDefaultNamespace(String uri) throws XMLStreamException {
// intentionally doing nothing
}
@Override
public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
super.writeStartElement(null, local, null);
}
@Override
public void writeStartElement(String uri, String local) throws XMLStreamException {
super.writeStartElement(null, local);
}
@Override
public void writeEmptyElement(String uri, String local) throws XMLStreamException {
super.writeEmptyElement(null, local);
}
@Override
public void writeEmptyElement(String prefix, String local, String uri) throws XMLStreamException {
super.writeEmptyElement(null, local, null);
}
@Override
public void writeAttribute(String prefix, String uri, String local, String value) throws XMLStreamException {
super.writeAttribute(null, null, local, value);
}
@Override
public void writeAttribute(String uri, String local, String value) throws XMLStreamException {
super.writeAttribute(null, local, value);
}
}
The main idea is to avoid passing namespace information to the underlying XMLStreamWriter. Hope this will help you to save some time solving similar problem.
PS. It's not necessary to extend DelegatingXMLStreamWriter in your code. I've done this to show which methods need changing.
There is a very simple way to get rid of namespace prefixes in your case: just set the attribute elementFormDefault to unqualified in your schema, like this:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:your="http://www.stackoverflow.com/your/namespace">
You will get the namespace prefix only in the first tag:
<ns1:your xmlns:ns1="http://www.stackoverflow.com/your/namespace">
I hope this helps.
Regards Pawel Procaj
For me, simply calling xmlStreamWriter.setDefaultNamespace("")
solved the issue.
One more thing you have to care in order to remove the namespace prefix from the output is that everywhere you have @XmlElement ensure it does not include the namespace property like @XmlElement(name="", namespace"http://...")
; otherwise, none of solutions will work.