I'm using SimpleXml to (de)serialize POJOs. Now, I have a big XML which has some elements which are not needed. For instance, with this XML:
<Root>
<Element>Used</Element>
<Another>Not used</Another>
<Root>
I want to create a POJO which looks like:
#Root
class Root{
#Element
private String element;
}
Problem is that I'm getting this Exception:
simpleframework.xml.core.ElementException: Element 'Another' does not have a
match in class blah.blah.Blah at line 1
So... how should I configure the POJO so that I can parse the XML correctly?
Set strict to false within the Root annotation to ignore any XML elements or attributes that do not appear in the class.
#Root(strict=false)
Alternatively, set strict to false when you read the xml in the serialiser:
Root root = serializer.read(Root.class, source, false);
you can add (required=false) to a single element
#Element(required=false)
private int statusCode;
if you have more elements use
#Root(strict=false)
Related
I would like to deserialize an XML subtree as string (with Jackson) in JAVA:
input structure:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<nodeA>text</nodeA>
<nodeB>
<nodeS>
<nodeS1>...</nodeS1>
<nodeS2>...</nodeS2>
</nodeS>
</nodeB>
</root>
into something like this:
public class Pojo {
#JacksonXmlProperty(localName="nodeA")
private String nodeA; // = "text"
#JacksonXmlProperty(localName="nodeB")
#JsonDeserialize(using = MyXmlDeserializer.class)
private String nodeB; // = "<nodeS><nodeS1>...</nodeS1><nodeS2>...</nodeS2></nodeS>"
}
The node nodeS should be taken as "raw-value" without ANY modifications to the xml and put it into a String class member.
I've tried it with custom deserializer or as #JacksonRawValue with no avail.
if one just could access the raw value of the "currentNode", that would help a lot.
Any alternative (jackson-related) solutions welcome :-)
It's kind of a workaround rather than a solution, but it's possible to use XmlMapper inside your JsonDeserializer:
xmlMapper.writeValueAsString(jsonNode);
As a result you'll get Xml string again. But as I wrote, it's workaround and I don't like it gets from Xml to Json, and from Json to Xml again.
If anyone get a better solution (using Jackson), please share.
I use javax and some XmlAdapters to generate XML. In the adapter I return an empty string as symbol for the presence of the value and null for absence.
The resulting XML looks like:
<ex:Example></ex:Example>
, which is correct and validates to my XSD (fixed="" minOccurs="0").
What I want is a self enclosed tag like:
<ex:Example/>
I have only found solutions for the opposite problem.
Is there a way to configure the Marshaller or JAXBContext to output XML to my taste?
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.
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:
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.
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).
I have an XML document that looks something like the following:
Note that I cannot change the schema because it is part of a standard XML Schema (Library of Congress METS).
<amdSec ID="AMDSEC001">
<digiprovMD ID="DMD001">
<mdWrap MDTYPE="OBJECT">
<xmlData>
<object xsi:type="file">
.....
</object>
</xmlData>
</mdWrap>
</digiprovMD>
<digiprovMD ID="DMD001_EVENT">
<mdWrap MDTYPE="EVENT">
<xmlData>
<event xsi:type="event">
.....
</event>
</xmlData>
</mdWrap>
</digiprovMD>
</amdSec>
As you can see, the inner element <mdWrap> can contain elements of different types; in this case they're <event> and <object>, but it isn't constrained to just those two types. Creating two classes (like below), marshals okay, but this doesn't work for unmarshalling.
class ObjectMDWrap {
#XmlElementWrapper(name = "xmlData")
#XmlElement(name = "object")
List<MyObject> object; //Wrapped in list to use #XmlElementWrapper
}
class EventMDWrap {
#XmlElementWrapper(name = "xmlData")
#XmlElement(name = "event")
List<MyEvent> event; //Wrapped in list to use #XmlElementWrapper
}
What can I do so that JAXB unmarshals the correct "type" of MDWrap?
I think, the best solution in this case is a generating POJO classes using XJC tool.
Download XSD file which describe XML file.
Using XJC tool convert XSD file into POJO classes. If XSD is not correct - fix it.
Make some changes if you need in generated classes.
Use this classes in marshalling / unmarshalling process.
I was able to figure out the solution, and it's much simpler than I initially thought (which speaks to my relative inexperience with XML and JAXB). By creating my MDWrap class in the following way
class MDWrap {
#XmlAnyElement(lax = true)
#XmlElementWrapper(name = "xmlData")
Object wrappedMD;
}
Then MDWrap can contain an object of any type, and will unmarshal properly, as long as the class of which wrappedMD is an instance of is annotated with #XmlRootElement. The trick is to annotate wrappedMD as XmlAnyElement.
Is there any way to just ignore an element from Jaxb parsing?
I have a large XML file, and if I could ignore one of the large, complex elements, then it would probably parse a lot quicker.
It would be even better if it could not even validate the element contents at all and parse the rest of the document even if that element is not correct.
ex:this should only generate Foo.element1 and Foo.element2
<foo>
<element1>I want this</element1>
<element2>And this</element2>
<bar>
<a>ALL of bar should be ignored</a>
<b>this also should be ignored</b>
<c>
<x>a lot of C that take time to process</x>
</c>
<c>
<x>a lot of C that take time to process</x>
</c>
<c>
<x>a lot of C that take time to process</x>
</c>
<c>
<x>a lot of C that take time to process</x>
</c>
</bar>
</foo>
Assuming your JAXB model looks like this:
#XmlRootElement(name="foo")
public class Foo {
#XmlElement(name="element1")
String element1;
#XmlElement(name="element2")
String element2;
#XmlElement(name="bar")
Bar bar;
}
then simply removing the bar field from Foo will skip the <bar/> element in the input document.
Alternatively, annotated the field with #XmlTransient instead of #XmlElement, and it will also be skipped.
JAXB will ignore any unmapped properties.
Implementation wise (atleast in EcliseLink JAXB (MOXy), which I lead). When we are processing the contents via a SAX parser (i.e. the input was a SAXSource) then we swap out our ContentHandler that is responsible for building objects to one that does no processing for that section (org.eclipse.persistence.oxm.unmapped.UnmappedContentHandler). When a we are using processing the contents via a StAX parser we just advance to the next mapped event.
If you do have a property that corresponds to that node you can annotate it with #XmlTransient to make it an unmapped property.
All what you need it's mark field as #XmlTransient (#XmlTransient annotation which should hide fields that are not required). Example below
JavaEE:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "DeletedIds")
public class DeletedIds {
#XmlElement(name = "DeletedId")
private List<DeletedId> id;
#XmlTransient
#XmlElement(name = "success")
private String success;
//getters&setters
}
#XmlAccessorType(XmlAccessType.FIELD)
public class DeletedId {
private int id;
//getters&setters
}
Xml:
<DeletedIds>
<DeletedId>
<id>1</id>
</DeletedId>
<DeletedId>
<id>2</id>
</DeletedId>
</DeletedIds>
You have to use a SAX parser, and a document handler that effectively "skips" the node of non-interest. You can't get around reading the bytes, but at least you can get around having them waste extra resources.
If your code requires a DOM tree, then you basically use a SAX document handler that generates DOM nodes, but "skips" the nodes of non-interest. Definitely less convenient that using the supplied DOM tree generators, but a decent trade-off is you can't live with the extra memory overhead of the unwanted nodes but you need the DOM tree.