Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB Ignore 'extra' elements from Response XML

I am getting a XML response and it keeps on changing very frequently (nodes keep on increasing or reducing). After each updation in response xml my code breaks as my mapped Java class does not have all fileds.

Is there any way to avoid my code breaking if any changes occurs in response XML.

Any help will be appreciated.

Thanks.

like image 577
Arpit Aggarwal Avatar asked Sep 02 '14 10:09

Arpit Aggarwal


2 Answers

Use JAXB.unmarshal() to simply create Java objects from XML.

By default it is very liberal.

Quoting from the javadoc:

In addition, the unmarshal methods have the following characteristic:

  1. Schema validation is not performed on the input XML. The processing will try to continue even if there are errors in the XML, as much as possible. Only as the last resort, this method fails with DataBindingException.

So what JAXB.unmarshal() does is it tries to "transfer" as much data from XML to Java as possible, and it doesn't care if there is no Java field for an XML element or attribute, and it also doesn't care if there is a Java field for which there is no XML element or attribute.

Example

Let's try to unmarshal the following XML to an instance of java.awt.Point:

<p hi="Yo">
    <y>123</y>
    <peach>weor</peach>
</p>

The Java code:

String s = "<p hi=\"Yo\"><y>123</y><peach>weor</peach></p>";
Point p = JAXB.unmarshal(new StringReader(s), Point.class);
System.out.println(p); // Prints "java.awt.Point[x=0,y=123]"

We told JAXB.unmarshal() to parse a java.awt.Point instance. The input XML contains an element <y> which can be matched with Point.y so an int was parsed and set to Point.y. No XML data was found for Point.x so it was not touched. There were no match for the attribute hi and the XML element <peach>, so they were simply not used for anything.

We got absolutely no Exception here, and the most that was possible was parsed and transferred from XML to Java.

like image 142
icza Avatar answered Sep 22 '22 17:09

icza


To cope with unknown fields, you can add a List<Object> property annotated @XmlAnyElement(lax=true)

@XmlAnyElement(lax = true)
private List<Object> anything;

Any elements in the input that do not correspond to explicit properties of the class will be swept up into this list. If the element is known to the JAXBContext you'll get the unmarshalled form (the @XmlRootElement annotated class or a JAXBElement<Foo>), if the element is not known to the context you'll get an org.w3c.dom.Element.

Full details in Blaise's blog.

For nodes that get removed you should be fine as long as you use types that can be null (Integer rather than int, Boolean rather than boolean, etc).

like image 42
Ian Roberts Avatar answered Sep 25 '22 17:09

Ian Roberts