Arnaud Denoyelle Arnaud Denoyelle - 1 year ago 360
Java Question

Jaxb ignore the namespace on unmarshalling

I use Jaxb2 and Spring. I am trying to unmarshal some XML that are sent by 2 of my customers.

Up to now, I only had to handle one customer which sent some xml like this :

<foo xmlns="com.acme">

that is bound to a POJO like this :

@XmlType(name = "", propOrder = {"bar"})
@XmlRootElement(name = "Foo")
public class Foo {

@XmlElement(name = "Bar")
private String bar;


I discovered that the previous developer hardcoded the namespace in the unmarshaller in order to make it work.

Now, the second customer sends the same XML but changes the namespace!

<foo xmlns="">

Obviously, the unmarshaller fails to unmarshall because it expects some
instead of
. Unforunately, asking the customer to change the XML is not an option.

What I tried :

1) In
, I searched for a configuration which would allow me to ignore the namespace but could not find one :

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="packagesToScan">
<property name="marshallerProperties">
<entry key="???"><value type="java.lang.Boolean">false</value></entry>

it seems that the only available options are the ones listed in the Jaxb2Marshaller's Javadoc :

* Set the JAXB {@code Marshaller} properties. These properties will be set on the
* underlying JAXB {@code Marshaller}, and allow for features such as indentation.
* @param properties the properties
* @see javax.xml.bind.Marshaller#setProperty(String, Object)
* @see javax.xml.bind.Marshaller#JAXB_ENCODING
* @see javax.xml.bind.Marshaller#JAXB_FORMATTED_OUTPUT
* @see javax.xml.bind.Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION
* @see javax.xml.bind.Marshaller#JAXB_SCHEMA_LOCATION
public void setMarshallerProperties(Map<String, ?> properties) {
this.marshallerProperties = properties;

2) I also tried to configure the unmarshaller in the code :

try {
jc = JAXBContext.newInstance("com.mycompany.mypkg");

Unmarshaller u = jc.createUnmarshaller();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(false);//Tried this option.

DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(xmlFile.toFile());
u.unmarshal(new DOMSource(doc));
return (Foo)u.unmarshal(new StreamSource(xmlFile.toFile()));
} catch (ParserConfigurationException | SAXException | IOException | JAXBException e) {
LOGGER.error("Erreur Unmarshalling CPL");

3) Different form with a SAXParser :

try {
jc = JAXBContext.newInstance("com.mycompany.mypkg");
Unmarshaller um = jc.createUnmarshaller();
final SAXParserFactory sax = SAXParserFactory.newInstance();
final XMLReader reader = sax.newSAXParser().getXMLReader();
final Source er = new SAXSource(reader, new InputSource(new FileReader(xmlFile.toFile())));
return (Foo)um.unmarshal(er);
}catch(...) {[...]}

This one works! But still, I would prefer to be able to autowire the Unmarshaller without needing this ugly conf everytime.

Answer Source

Namesapce awareness is feature of the document reader/builder/parser not marshallers. XML elements from different namespaces represents different entities == objects, so marshallers cannot ignore them.

You correctly switched off the namespaces in your SAX reader and as you said it worked. I don't understand your problem with it, your marshaller still can be injected, the difference is in obtaining the input data.

The same trick with document builder should also work (I will test it later on), I suspect that you were still using the marshaller with "hardcoded" namespace but your document was namespace free.

In my project I use XSLT to solve similar issue. Setting namespace awarness is definitely easier solution. But, with XSLT I could selectviely remove only some namespaces and also my my input xml are not always identical (ignoring namespaces) and sometimes I have to rename few elements so XSLT gives me this extra flexibility.

To remove namespaces you can use such xslt template:

<xsl:stylesheet version="1.0" xmlns:e="http://timet.dom.robust.ed" xmlns:xsl="" xmlns:xsi="">
<xsl:template match="/"> 
        <xsl:apply-templates />

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="@* | node()" />

<xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
        <xsl:value-of select="."/>

<xsl:template match="text() | processing-instruction() | comment()">
    <xsl:copy />

Then in Java before unmarshalling I transform the input data:

Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
Source source = new DOMSource(xml);
DOMResult result = new DOMResult();
transformer.transform(source, result);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download