I have JAXB objects created from a schema. While marshalling, the xml elements are getting annotated with ns2. I have tried all the options that exist over the net for this problem, but none of them works. I cannot modify my schema or change package-info.java. Please help
-
Another solution mentioned here [http://stackoverflow.com/a/29945934/4745777][1] [1]: http://stackoverflow.com/a/29945934/4745777 – HamedKhan Apr 29 '15 at 14:04
5 Answers
After much research and tinkering I have finally managed to achieve a solution to this problem. Please accept my apologies for not posting links to the original references - there are many and I wasn't taking notes - but this one was certainly useful.
My solution uses a filtering XMLStreamWriter
which applies an empty namespace context.
public class NoNamesWriter extends DelegatingXMLStreamWriter {
private static final NamespaceContext emptyNamespaceContext = new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
return "";
}
@Override
public String getPrefix(String namespaceURI) {
return "";
}
@Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
};
public static XMLStreamWriter filter(Writer writer) throws XMLStreamException {
return new NoNamesWriter(XMLOutputFactory.newInstance().createXMLStreamWriter(writer));
}
public NoNamesWriter(XMLStreamWriter writer) {
super(writer);
}
@Override
public NamespaceContext getNamespaceContext() {
return emptyNamespaceContext;
}
}
You can find a DelegatingXMLStreamWriter
here.
You can then filter the marshalling xml with:
// Filter the output to remove namespaces.
m.marshal(it, NoNamesWriter.filter(writer));
I am sure there are more efficient mechanisms but I know this one works.

- 1
- 1

- 64,482
- 16
- 119
- 213
-
3in case you don't want to use cxf, import the jaxws-rtxxx.jar then using the standard jawx-ws does the same trick by code the following: class NoNamesWriter extends XMLStreamWriterFilter, – Junchen Liu Dec 10 '15 at 15:00
For me, only changing the package-info.java class worked like a charm, exactly as zatziky stated :
package-info.java
@javax.xml.bind.annotation.XmlSchema
(namespace = "http://example.com",
xmlns = {@XmlNs(prefix = "", namespaceURI = "http://example.com")},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package my.package;
import javax.xml.bind.annotation.XmlNs;

- 151
- 1
- 4
-
2If you use xjc to generate jaxb artifacts from an xsd through a .xjb file, the package-info.java is genereated and you should not manually change it. If you use Maven to run xjc, you can use the the maven-jaxb2-plugi together with the https://github.com/Siggen/jaxb2-namespace-prefix. This allows to add namespace prefixes to the .xjb file (which is the input to xjc to customize how code is generated). – Henno Vermeulen Aug 16 '18 at 12:42
-
This is the cleanest solution for me as long you don't need to mix different element from different namespaces. This is always my preferred way than writing a lot of code. – рüффп Jul 22 '22 at 07:00
You can let the namespaces be written only once. You will need a proxy class of the XMLStreamWriter and a package-info.java. Then you will do in your code:
StringWriter stringWriter = new StringWriter();
XMLStreamWriter writer = new Wrapper((XMLStreamWriter) XMLOutputFactory
.newInstance().createXMLStreamWriter(stringWriter));
JAXBContext jaxbContext = JAXBContext.newInstance(Collection.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
jaxbMarshaller.marshal(books, writer);
System.out.println(stringWriter.toString());
Proxy class (the important method is "writeNamespace"):
class WrapperXMLStreamWriter implements XMLStreamWriter {
private final XMLStreamWriter writer;
public WrapperXMLStreamWriter(XMLStreamWriter writer) {
this.writer = writer;
}
//keeps track of what namespaces were used so that not to
//write them more than once
private List<String> namespaces = new ArrayList<String>();
public void init(){
namespaces.clear();
}
public void writeStartElement(String localName) throws XMLStreamException {
init();
writer.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
init();
writer.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
init();
writer.writeStartElement(prefix, localName, namespaceURI);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
if(namespaces.contains(namespaceURI)){
return;
}
namespaces.add(namespaceURI);
writer.writeNamespace(prefix, namespaceURI);
}
// .. other delegation method, always the same pattern: writer.method() ...
}
package-info.java:
@XmlSchema(elementFormDefault=XmlNsForm.QUALIFIED, attributeFormDefault=XmlNsForm.UNQUALIFIED ,
xmlns = {
@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")})
package your.package;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
You can use the NamespacePrefixMapper
extension to control the namespace prefixes for your use case. The same extension is supported by both the JAXB reference implementation and EclipseLink JAXB (MOXy).

- 147,609
- 23
- 300
- 400
-
Hi, I have been following your answers lately for my project which is building XML. I am using the `Moxy` to create XML using the `Marshalling` approach. For some reason, the generated XML takes the default namespaces such as `ns0, ns1, etc` even though I have provided my own custom prefix while creating the `QName`. Can you please have a look at this question and provide your suggestion: https://stackoverflow.com/questions/67553941/creation-of-qname-takes-default-namesapce-prefix-rather-than-the-provided-parame – BATMAN_2008 May 16 '21 at 12:13
Every solution requires complex overwriting or annotations which seems not to work with recent version. I use a simpler approach, just by replacing the annoying namespaces. I wish Google & Co would use JSON and get rid of XML.
kml.marshal(file);
String kmlContent = FileUtils.readFileToString(file, "UTF-8");
kmlContent = kmlContent.replaceAll("ns2:","").replace("<kml xmlns:ns2=\"http://www.opengis.net/kml/2.2\" xmlns:ns3=\"http://www.w3.org/2005/Atom\" xmlns:ns4=\"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0\" xmlns:ns5=\"http://www.google.com/kml/ext/2.2\">", "<kml>");
FileUtils.write(file, kmlContent, "UTF-8");

- 447
- 7
- 21