JAXB facilities in unmarshaling - java

Hello guys how can i unmarshall list of objects in XML. My XML will be like this
<messageContainer class="class1">
<a>
<b />
</a>
<MessageB />
</messageContainer>
<messageContainer class="class2">
<a>
<b />
</a>
<MessageB />
</messageContainer>
And i want to get list of object in the end.

Any Valid XML file can contain only one XML Root Element.
I assume that u have the above list as a child of an RootElement(say ).
Then your annotated RootElement class should look like this.
#XmlRootElement(name = "RootElement")
public class RootElement{
#XmlElement(name = "messageContainer", required = true)
private List<messageContainer> containerList;
}
Where MessageContainer is a class by itself.
Note : The more simpler way to generate these binding class is, write XSD(or generate using online tools) for your XML and compile those XSD with XJC compiler.

Related

Using Jackson to parse XML with repeated element

I am looking for a simple way to parse an XML structure with a repeated element using Jackson. Here is a simplified example:
<root>
<a>
<x>
<b>some content</b>
<c>some content</c>
</x>
<x>
<b>some content</b>
<c>some content</c>
</x>
...
<x>
<b>some content</b>
<c>some content</c>
</x>
</a>
... some other content ...
</root>
I would like to collect all the x elements in a list or array The problem is that when using something like:
XmlMapper().readTree(xml).get("a").fields()
the result contains only the last instance of x so it looks like some map key gets overwritten. There is a solution using JsonParser
e.g.: XmlMapper().createParser(xml) but it's a bit icky.
Is there a better way?
Edit
The way I read the "Known Limitations" section in the README , XML seems to be a second class citizen in Jackson. I accept #galuszkak 's answer as it is what it is , but to my mind when a developer invokes XmlMapper().readTree(xml) they do not expect XML processing to be shoehorned into JSON processing model with the limitations that come with that approach.
The problem mentioned here is described in this Github issue:
https://github.com/FasterXML/jackson-dataformat-xml/issues/187
Basically what is happening is that Jackson is translating XML tree structure in JsonNode data model and this will not work as it's not supported.
There is 2 options described in that Github issue:
Fully transform this XML to JSON (answer from #cawena on Github)
Or if you know your data structure to just use answer from p0sitron which is:
Code:
List<List<JsonNode>> elA = xmlMapper.readValue(xml, new TypeReference<List<List<JsonNode>>>() { });
assertEquals(3, elA.get(0).size());

XPath how to check if an ancestor element has a certain name

I have an element structure like so:
<template>
<x name="foo">
<y>
<x>
<a>
<b number="1" />
<c>2</c>
</a>
</x>
<c>5</c>
</y>
</x>
</template>
I need it so that a b element can only exist in a as long as one of the ancestors is an x with a name. I have a set of alternatives written, but I can't get the test to work. This is what I thought would work:
ancestor::x[#name]
but I get no result. The only xpath I've had luck with is this:
ancestor::node()
Can anyone tell me what I'm missing?
Edit:
I'm using a java xerces 2.11 library to load an xsd file which includes tags.
I tried using below xpath and it gave me proper result. I hope you are using proper context for ancestor element.
//template//b/ancestor::x[#name]
Output result is as below :
Element='<x name="foo">
<y>
<x>
<a>
<b number="1" />
<c>2</c>
</a>
</x>
<c>5</c>
</y>
</x>'
As per your condition, the xpath will be :
//template//b[ancestor::x[#name]]
And the output will be as below which will only be given if it has ancestor element 'x' with name attribute :
Element='<b number="1" />'

JAXB Annotation binding XML content as String

I want to bind a XML content as a String to the field.
Here is how my xml seems like:
<sample>
<content>
<p>here is content <b>with bold</b></p>
</content>
</sample>
which should be bound to the following domain object:
#Entity
#Table(name="news_table")
#XmlRootElement
class Sample {
#XmlElement(name="content")
#Column(name="news_content")
private String content;
}
After unmarshalling, i want to bind the content starts with <p> as String type in order to persist formatted text with HTML tags, so that:
System.out.println(sample.getContent());
must give the following out:
> "<p>here is content <b>with bold</b></p>"
With #XmlElement annotation i get only empty string "" back from binding operation, since the JAXB recognize the element starts with "<p>" as Object to be bound according to my understanding.
Any suggestion ?
Try using #XmlAnyElement annotation with a custom DomHandler. You can find an example here.
If it is an option to change the content of the xml file, you could just escape the < and >. Then JAXB handles it just fine and you also get the correct html string when calling getContent() in java.
Here is your xml file with escaped content:
<sample>
<content><p>here is content <b>with bold</b></p></content>
</sample>

XML parsing in JAVA with JAXB Annotations

I need following Kind of XML in result from a JAVA class using JAXB annotation(like #XmlElement , #XmlAttribute etc.)
Following is the XML result that i want...
<?xml version="1.0" ?>
<ROOT>
<A>
<A1></A1>
<A2></A2>
</A>
<B>
<B1></B1>
<B2></B2>
</B>
</ROOT>
For that XML response what should be my Sample Java Class and what should be the annotations for that, keeping in mind that all the nodes should be case-sensitive ie. element B shouldn't b
Thanks in advance

JAXB Does not Marshall as Expected

A buddy of mine asked me to post this question:
EDIT: He decided to post the question on his own here: JAXB Unmarshalls XML Incorrectly I tried to delete this question but couldn't.
I am trying to marshall a java class, called MyContainer. This class extends my another class, called Container. Container has a variable called: protected List<ResourceReference<Component>> child
The only variable MyContainer has is the one it inherits from Container. This List, however, will not marshall with JAXB when I have child listed as an XmlList.
It will marshall as an XmlElement, however this is not how I want the data displayed. When it is marshalled as an XmlElement, it lists the attributes in the List, but not 'heirarchially' It just lists the two elements as if they were properties of the class, as opposed to belonging to the child list.
How do I get Jaxb to marshall the List (Which is instantiated as an ArrayList) correctly?
EDIT: Here's an example:
This is what I am getting:
<MyContainer name="Container Name">
<booleanVal>false</booleanVal>
<child id="Test Comp 1"/>
<child id="Test Comp 2"/>
</and>
This is more what I expect:
<MyContainer name="Container Name">
<booleanVal>false</booleanVal>
<child> /// This would be the class variable of the extended Class, Container
<ResourceRef id="Entry 1">
<ResourceRef id="Entry 2">
</child>
</and>
Admittly, my current results is probably from the List in Container being marked with the #XmlElement annotation. However, JAXB will not marshall anything else..
Annotate your list with #XmlElementWrapper. See javadoc.

Categories

Resources