XStream multiple node types in subscribers collection

I am trying to deserialize an XML document like this:

<rootelem> <elementType1 arg1="..." /> <elementType1 arg1="..." /> <elementType1 arg1="..." /> <elementType2 argA="..." argB="..." /> <elementType2 argA="..." argB="..." /> <elementType2 argA="..." argB="..." /> </rootelem> 

By default, XStream can only analyze this form:

 <rootelem> <list1> <elementType1 arg1="..." /> <elementType1 arg1="..." /> <elementType1 arg1="..." /> </list1> <list2> <elementType2 argA="..." argB="..." /> <elementType2 argA="..." argB="..." /> <elementType2 argA="..." argB="..." /> </list> </rootelem> 

This is because XStream uses the following format for collections:

 <collection> <elem .... /> <elem .... /> <elem .... /> </collection> 

and frame tags are required. A collection can contain only nodes of the same type. So how can I parse such an XML document? Now I have written my own converter for this, but I wonder if there are other ways?

0
source share
2 answers

I think Implicit Collections is the solution for you.

http://x-stream.imtqy.com/alias-tutorial.html#implicit

Here is a sample code:

 package com.thoughtworks.xstream; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { Blog teamBlog = new Blog(new Author("Guilherme Silveira")); teamBlog.add(new Entry("first","My first blog entry.")); teamBlog.add(new Entry("tutorial", "Today we have developed a nice alias tutorial. Tell your friends! NOW!")); XStream xstream = new XStream(); xstream.alias("blog", Blog.class); xstream.alias("entry", Entry.class); xstream.addImplicitCollection(Blog.class, "entries"); System.out.println(xstream.toXML(teamBlog)); } } 

And the result:

 <blog> <author> <name>Guilherme Silveira</name> </author> <entry> <title>first</title> <description>My first blog entry.</description> </entry> <entry> <title>tutorial</title> <description> Today we have developed a nice alias tutorial. Tell your friends! NOW! </description> </entry> </blog> 
+1
source

The first thing you need to do is create a POJO for all of your core XML tags. I assume that the example you provided is not the actual XML that you need for "unmarshall" (this XML lingua for deserialization), but I will skate with it in order to give you an example to work with; -).

 public class ElementType1 { private String arg1; public ElementType1() { setArg1(""); } public String getArg1() { return arg1; } public void setArg1(String newArg1) { arg1 = newArg1; } } public class ElementType2 { private String argA; private String argB; public ElementType2() { setArgA(""); setArgB(""); } public String getArgA() { return argA; } public void setArgA(String newArgA) { argA = newArgA; } public String getArgB() { return argB; } public void setArgB(String newArgB) { argB = newArgB; } } public class RootElement { private List<ElementType1> element1s; private List<ElementType2> element2s; public RootElement() { setElement1s(new ArrayList<ElementType1>()); setElement2s(new ArrayList<ElementType2>()); } public List<ElementType1> getElement1s() { return element1s; } public void setElement1s(List<ElementType1> newElement1s) { element1s = newElement1s; } public List<ElementType2> getElement2s() { return element2s; } public void setElement2s(List<ElementType2> newElement2s) { element2s = newElement2s; } } 

Now that you have your POJOs, using XStream to sort (serialize) and unmarshall (deserialize) them in and out of XML is pretty simple.

 List<ElementType1> e1 = new ArrayList<ElementType1>(); List<ElementType2> e2 = new ArrayList<ElementType2>(); ElementType1 a, b, c; a = new ElementType1(); b = new ElementType1(); c = new ElementType1(); a.setArg1("fizz"); b.setArg1("buzz"); c.setArg1("foo"); e1.add(a); e1.add(b); e1.add(c); ElementType2 d, e; d = new ElementType2(); e = new ElementType2(); d.setArgA("flim"); d.setArgB("flam"); e.setArgA("something"); e.setArgB("blah"); e2.add(d); e2.add(e); RootElement rootElem = new RootElement(); rootElem.setElement1s(e1); rootElem.setElement2s(e2); XStream xstream = new XStream(); RootElement rootElem = getYourRootElementSomehow(); String rootElementAsXml = xstream.toXML(rootElem); System.out.println(rootElementAsXml); 

Now this code will output the following to the console:

 <fully.qualified.pkg.name.RootElement> <element1s> <fully.qualified.pkg.name.ElementType1> <arg1>fizz</arg1> </fully.qualified.pkg.name.ElementType1> <fully.qualified.pkg.name.ElementType1> <arg1>buzz</arg1> </fully.qualified.pkg.name.ElementType1> <fully.qualified.pkg.name.ElementType1> <arg1>foo</arg1> </fully.qualified.pkg.name.ElementType1> </element1s> <element2s> <fully.qualified.pkg.name.ElementType2> <argA>flim</argA> <argB>flam</argB> </fully.qualified.pkg.name.ElementType2> <fully.qualified.pkg.name.ElementType2> <argA>something</argA> <argB>blah</argB> </fully.qualified.pkg.name.ElementType2> </element2s> </fully.qualified.pkg.name.RootElement> 

You can then clear the disgusting, fully qualified package with the name of the XML elements using the universal XStreams aliases, for example:

 xstream.alias("elementType1", ElementType1.class); xstream.alias("elementType2", ElementType2.class); xstream.alias("rootElement", RootElement.class); String rootElementAsXml = xstream.toXML(rootElem); System.out.println(rootElementAsXml); 

which will now be printed:

 <rootElement> <element1s> <elementType1> <arg1>fizz</arg1> </elementType1> <elementType1> <arg1>buzz</arg1> </elementType1> <elementType1> <arg1>foo</arg1> </elementType1> </element1s> <element2s> <elementType2> <argA>flim</argA> <argB>flam</argB> </elementType2> <elementType2> <argA>something</argA> <argB>blah</argB> </elementType2> </element2s> </rootElement> 

Now I know that in your example, you wanted all <arg> actually attributes of the <elementType> tags, and not the tags themselves for the children. You can use the powerful XStream API to do this for you as you like. But hopefully this is enough to get you started.

And by the way, turning your XML back into POJO is just as easy:

 RootElement root = (RootElement)xstream.fromXML(rootElementAsXml); 

Typically, XStream is an "oxmapper" (Object-XML Mapper), and it is created in advance to know how to turn POJO into meaningful XML and vice versa. You can always override your default values, but more often than not I was not always surprised at how smart its default values ​​are. Good luck to you.

0
source

Source: https://habr.com/ru/post/1437294/


All Articles