How to serialize POJO to xml with namespace prefix

ltfishie picture ltfishie · Apr 5, 2014 · Viewed 7.4k times · Source

Spring offers several ways to convert POJO to XML through HttpMessageConverter. However, I am having quite a bit of difficulty finding one that supports custom namespace with prefix.

For example from

public class Student {
   String name;
   String address;
   Integer score;
}

To

<?xml version="1.0" encoding="UTF-8"?> 
<foo:Student xmlns:foo="http://schemas.foo.com/student">
   <foo:name>Some Name</foo:name>
   <foo:address>Address</foo:address>
   <foo:score>95</foo:score>
</foo:Student>

I was happily using MappingJackson2HttpMessageConverter with jackson-dataformat-xml until I realized that it does not support custom prefix.

Then I looked into using MarshallingHttpMessageConverter with XStreamMarshaller, only to find out that XStream does not support custom prefix either.

Can anyone refer me to a example how I can serialize POJO to xml with custom namespace prefix? Thanks.

Answer

ciekawy picture ciekawy · Jun 20, 2014

I have managed to resolve similar problem for Jackson. First you have to use woodstox XML processor.

<dependency>
  <groupId>org.codehaus.woodstox</groupId>
  <artifactId>woodstox-core-asl</artifactId>
  <version>4.4.0</version>
</dependency>

Than I have added namespace perfix/uri mapping this way:

  XmlMapper mapper = new XmlMapper();
  // override default instance of WstxOutputFactory
  mapper.getFactory().setXMLOutputFactory(new WstxOutputFactory() {
    @Override
    public XMLStreamWriter createXMLStreamWriter(Writer w) throws XMLStreamException {
      mConfig.setProperty(WstxInputProperties.P_RETURN_NULL_FOR_DEFAULT_NAMESPACE,  true);
      XMLStreamWriter result = super.createXMLStreamWriter(w);
      result.setPrefix("xlink", "http://www.w3.org/1999/xlink");
      return result;
    }
  });

For sure this is not elegant soultion but I am not sure if there is any other way. I hope Jackson will add api support for prefixes in future release.

I guess however in your case default namespace with prefix is needed and this seems to be more difficult because Jackson does not support default namespace (https://github.com/FasterXML/jackson-dataformat-xml/issues/18) and even using class inheritance with @JacksonXmlRootElement(namespace="http://xmlns.uri.com") you still would need to annotate each property with @JacksonXmlProperty(namespace="http://xmlns.uri.com")