Deserialize XML in multiple objects using SimpleXML - java

I built xml files in Android from objects by appending multiple objects to the same file using Simple
<listOfBtDevices>
<devices class="java.util.ArrayList">
<BTDevice>
<address>00:27:13:A3:2D:14</address>
<bondState>NONE</bondState>
<deviceType>LAPTOP</deviceType>
<name>LTPH</name>
<services>AUDIO CAPTURE NETWORKING OBJECT_TRANSFER RENDERING TELEPHONY</services>
<rssi>-95</rssi>
</BTDevice>
<BTDevice>
<address>00:27:13:A3:2D:14</address>
<bondState>NONE</bondState>
<deviceType>LAPTOP</deviceType>
<name>LTPH</name>
<services>AUDIO CAPTURE NETWORKING OBJECT_TRANSFER RENDERING TELEPHONY</services>
<rssi>-95</rssi>
</BTDevice>
<BTDevice>
<address>00:27:13:A3:2D:14</address>
<bondState>NONE</bondState>
<deviceType>LAPTOP</deviceType>
<name>LTPH</name>
<services>AUDIO CAPTURE NETWORKING OBJECT_TRANSFER RENDERING TELEPHONY</services>
<rssi>-95</rssi>
</BTDevice>
</devices>
<timestamp>22.11.2013_10.56.44</timestamp>
</listOfBtDevices>
<listOfBtDevices>
<devices class="java.util.ArrayList">
<BTDevice>
<address>00:27:13:A3:2D:14</address>
<bondState>NONE</bondState>
<deviceType>LAPTOP</deviceType>
<name>LTPH</name>
<services>AUDIO CAPTURE NETWORKING OBJECT_TRANSFER RENDERING TELEPHONY</services>
<rssi>-95</rssi>
</BTDevice>
</devices>
<timestamp>22.11.2013_10.56.50</timestamp>
</listOfBtDevices>
In the example above the object is ListOfBtDevices which is compound of a (String)timestamp and an ArrayList of BTDevice. The question is how can I deserialize it in multiple ListOfBtDevice objects using Simple or other framework on the Desktop Computer?
Thank you and sorry if I made mistakes but I am beginner in JAVA.

First of all, for you to be able to deserialize the xml file it needs to have one single root node. not multiple like in your case.
You have:
<listOfBtDevices>
...
</listOfBtDevices>
<listOfBtDevices>
...
</listOfBtDevices>
What it should look like:
<root>
<listOfBtDevices>
...
</listOfBtDevices>
<listOfBtDevices>
...
</listOfBtDevices>
</root>
After that you need to deserialize using some framework like Simple or XStream. I would recommend Simple for your purposes and I will give you a rudimentary example using Simple:
To deserialize the XML into objects using Simple you have to create model classes which have the same structure like your xml. You describe how the Objects are mapped to XML using annotations like #Element or #Attribute. In your case it would look something like this:
First you need a class which corresponds to your root node:
// The name you enter here is how the root node is called in your xml
#Root(name = "root")
public class BluetoothDeviceListContainer {
// It contains a List, inline is set to true because the list items are directly inside the root node, each entry is called "listOfBtDevices"
#ElementList(entry = "listOfBtDevices", inline = true)
List<BluetoothDeviceList> bluetoothDeviceList;
}
And you continue to do this until you have fully described your xml with classes. Next you would create a Class BluetoothDeviceList which corresponds to the "listOfBtDevices" nodes and enter which elements and attributes are contained and this class etc.
When you are finished you can deserialize your xml like this:
Serializer serializer = new Persister();
BluetoothDeviceListContainer container = serializer.read(BluetoothDeviceListContainer.class, xmlAsString);
After adding some getters and if you need setters to your model classes you can access all deserialized properties like this:
BluetoothDeviceList list = container.get(0);
...
Here you can find a complete tutorial for Simple and here some additional examples.

Related

Change text in reusable pipeline in DKPro

This questions describes how to reuse a pipeline in dkpro but if I only create one JCas and then try to change the text then I get the exception
org.apache.uima.cas.CASRuntimeException: Data for Sofa feature setLocalSofaData() has already been set.
How do I get around this?
The sofa data in the CAS can only be set once. It cannot be modified after it has been set.
In order to re-use a CAS, call the reset() method on it. This clears all annotations and allows you to set the sofa/text again.
To build a CAS incrementally, a common strategies is to add annotations to the CAS while adding text to a string buffer and setting the text only at the end of the process.
An uimaFIT-based example could look something like this:
Strings[] texts = {
"Hello world.",
"This is a test." };
// Create empty CAS/JCas initialized using uimaFIT typesystem auto-detection
JCas jcas = JCasFactory.createJCas();
// Instantiate some analysis engine
AnalysisEngine engine = AnalysisEngineFactory.createEngine(...);
// Process texts re-using the previously created CAS/JCas instance
for (String t : texts) {
jcas.reset();
jcas.setDocumentText(t);
jcas.setDocumentLanguage("en");
engine.process(jcas);
}
engine.collectionProcessComplete();
engine.destroy();
Disclosure: I am working on the Apache UIMA project.

Converting Hl7 message to Json

i need to convert the HL7 message to JSON so i used Hapi to convert the message to xml and then used a JSON library to convert the xml to JSON,The output for xml is
<?xml version="1.0" encoding="UTF-8"?>
<ADT_A01 xmlns="urn:hl7-org:v2xml">
<MSH>
<MSH.1>|</MSH.1>
<MSH.2>^~\&</MSH.2>
<MSH.3>
<HD.1>7EDIT</HD.1>
</MSH.3>
<MSH.4>
<HD.1>7EDIT.COM</HD.1>
</MSH.4>
<MSH.5>
<HD.1>IS</HD.1>
</MSH.5>
<MSH.6>
<HD.1>FACILITY</HD.1>
</MSH.6>
<MSH.7>20150721160705</MSH.7>
<MSH.8>S</MSH.8>
<MSH.9>
<MSG.1>ADT</MSG.1>
<MSG.2>A01</MSG.2>
</MSH.9>
<MSH.10>MSG00001</MSH.10>
<MSH.11>
<PT.1>P</PT.1>
</MSH.11>
<MSH.12>
<VID.1>2.6</VID.1>
</MSH.12>
<MSH.13>1</MSH.13>
<MSH.14>ST</MSH.14>
<MSH.15>AL</MSH.15>
<MSH.16>AL</MSH.16>
<MSH.17>972</MSH.17>
<MSH.18>WINDOWS-1252</MSH.18>
</MSH>
<EVN>
<EVN.1>A01</EVN.1>
<EVN.2>20150721160852</EVN.2>
<EVN.3>20150721160854</EVN.3>
<EVN.4>01</EVN.4>
<EVN.5>
<XCN.1>st</XCN.1>
</EVN.5>
<EVN.6>20150721160917</EVN.6>
<EVN.7>
<HD.1>IS</HD.1>
</EVN.7>
</EVN>
<PID>
<PID.1>1</PID.1>
<PID.2>
<CX.1>ST</CX.1>
<CX.4>
<HD.1>IS</HD.1>
</CX.4>
</PID.2>
<PID.3>
<CX.1>12345</CX.1>
</PID.3>
<PID.5>
<XPN.1>
<FN.1>JOSEPH</FN.1>
</XPN.1>
</PID.5>
</PID>
<PV1>
<PV1.2>B</PV1.2>
<PV1.3>
<PL.1>IS</PL.1>
</PV1.3>
<PV1.4>A</PV1.4>
<PV1.5>
<CX.1>S</CX.1>
</PV1.5>
<PV1.6>
<PL.1>S2</PL.1>
</PV1.6>
<PV1.7>
<XCN.1>REALM</XCN.1>
</PV1.7>
<PV1.8>
<XCN.1>HANNAH</XCN.1>
</PV1.8>
<PV1.9>
<XCN.1>DOCTOR</XCN.1>
</PV1.9>
<PV1.10>SUR</PV1.10>
<PV1.11>
<PL.1>PC</PL.1>
</PV1.11>
<PV1.12>S</PV1.12>
<PV1.13>R</PV1.13>
<PV1.14>7</PV1.14>
<PV1.15>A0</PV1.15>
<PV1.16>IN</PV1.16>
<PV1.17>
<XCN.1>NUMBER</XCN.1>
</PV1.17>
<PV1.18>AM</PV1.18>
<PV1.19>
<CX.1>NUM</CX.1>
</PV1.19>
<PV1.20>
<FC.1>FC</FC.1>
</PV1.20>
<PV1.21>PR</PV1.21>
<PV1.22>S</PV1.22>
<PV1.23>SS</PV1.23>
<PV1.24>S</PV1.24>
</PV1>
</ADT_A01>
Here the output is like segmenName.FieldName (MSH.1),so the Json is also the same ,instead of segmenName.FieldName ,i need to give a meanigful name to each field, i am unable to figure out how to do this
i need to map the element in Xml to a different key in JSON
One way of doing this is to have a mapping of fields/names, and traverse all your JSON looking for fields on the mapping, when a field is found, change it's name to the correspondent name in the mapping.
You might not be able to change the JSON you are traversing, in that case, the traverse should be cloning the structure, creating JSON nodes with the correspondent names.
Your JSON tool might have a way of parsing and traversing the whole JSON object recursively.
Another way is that you implement the XML-JSON conversion (it is really simple to do), and include the "name mapping" step into that conversion.

JAXB Multiple Content for Element

I'm currently working on a txt-to-xml project. Basically what I'm doing is creating different XmlElements for some of the content.
I got a DTD up and running and for now I'm creating a default xml, just to make sure every xml created is a valid xml (for the DTD given).
I'm mainly creating new Classes for every Element, which doesn't have a #PCDATA structure and it's working pretty fine so far.
Now I'm struggling with a problem:
I got the following in my DTD:
<!ELEMENT REACTION(#PCDATA | ACTOR*)>
What I'm looking for in my Text is something like:
Prof. X clapped!
and I want to extract this into my XML as:
<REACTION>
<ACTOR>Prof. X</ACTOR> clapped!
</REACTION>
So what I basically want is a String-Attribute within the ReactionClass which is devlares as XML-Element but holds an Actor-Attribute + Rest of the Text. I thought of something like:
String m_sText;
String m_sActor;
public ReactionClass(){
this.Actor = "Prof. X";
this.sText = this.m_sActor + " clapped!";
}
#XmlElement(name = "TEXT")
public String getM_sText(){ return this.m_sText; }
#XmlElement(name = "ACTOR")
public String getM_sActor(){ return this.m_sActor; }
For all other Nodes, such as the RootNode I created a RootNodeClass which holds different attributes, such as m_nLocation, m_nTime, m_nYear which are declared as XML-Elements, so the JAXB-Marshaller just builds up the XML on basis of these elements:
<ROOT>
<TIME>09:00</TIME>
<LOCATION>New York</TIME>
<YEAR>1992</YEAR>
</ROOT>
I wanted to do the same with the REACTION-Node (like mentioned above), but when creating a new Class REACTION I'm getting sth. like:
<REACTION>
<TEXT>Prof. X clapped!</TEXT>
<ACTOR>Prof. X</ACTOR>
</REACTION>
How would I put them into one Element but still keep the Tags such as above?
If anybody got an idea how to manage this I would be very thankful!
Thanks Max
First, what you most probably need is #XmlMixed. You'll probably have a structure like:
#XmlMixed
#XmlElementRefs({
#XmlElementRef(name="ACTOR", type=JAXBElement.class),
...})
List<Object> content;
With this you could put there Strings and JAXBElement<Actor> to achieve so-called mixed content.
Next, you might consider turning your DTD into XML Schema first and compiling it - or compiling the DTD with XJC.
Finally, what you have is so-called "semi-structured data" which I think is not quite suitable for JAXB. JAXB works great for strong and clear structures, but if you have mixed stuff you get weird models that are hard to work with. I can't suggest an alternative though.

Java DOM XML Parser with chaning namespaces

I do REST calls to a WebService and receive always XML as response. Then i'm parsing that XML und filling Java objects with those informations.
The Problem is that the element-tags could have different namespaces, like this:
<ns:title>....</ns:title>
or
<ns2:title>....<ns2:title>
or
<title>...<title>
EDIT:
And the namespace URIs look like this:
<ns2:feed xmlns="http://www.example.com/routing1/routing2"
xmlns:ns2="http://www.w3.org/../Atom"
xmlns:ns3="http://www.example.com/routing1/routing2"
xmlns:ns4="http://purl.org/routing1/routing2/1.0">
So therefore i changed the method element.getElementsByTagNameNS("specifiedNamespace", "title") to element.getElementsByTagNameNS("*", "title").
Is that okay to match all namespace, because i have also the case that the element-tag doesn't have a namespace like the third example <title>..</title>..
Is there a better procedure, to solve that problem? Or is it okay to solve it like, how i do it?
Thanks.
EDIT: 2 response examples
1.
<ns2:feed xmlns="http://www.example.com/routing1/routing2" xmlns:ns2="http://www.w3.org/../Atom" xmlns:ns3="http://www.example.com/routing1/routing2" xmlns:ns4="http://purl.org/routing1/routing2/1.0">
...
<ns2:someTag1>..</ns2:someTag1>
<ns2:title>title</ns2:title>
<entry>...</entry>
....
</ns2:feed>
2
<ns2:feed xmlns="http://www.w3.org/../Atom" xmlns:ns2="http://www.example.com/routing1/routing2" xmlns:ns3="http://www.example.com/routing1/routing2" xmlns:ns4="http://purl.org/routing1/routing2/1.0">
...
<someTag1>..<someTag1>
<title>title<title>
<ns2:entry>...</ns2:entry>
....
</ns2:feed>
Your title elements have the same namespace in both of your examples.
In the first example, you have:
xmlns:ns2="http://www.w3.org/../Atom"
and
<ns2:title>title</ns2:title>
so this means that title is in the http://www.w3.org/../Atom namespace.
In the second example, you have:
xmlns="http://www.w3.org/../Atom"
and
<title>title<title>
so here again title is in the http://www.w3.org/../Atom namespace.
The prefixes are different (the second example isn't using a prefix for title), but the namespace is the same.
This means that you should be able to use:
element.getElementsByTagNameNS("http://www.w3.org/../Atom", "title")
and it should successfully select the title element, even if the prefixes change.

parsing large XML using SAX in java

I am trying to parse the stack overflow data dump, one of the tables is called posts.xml which has around 10 million entry in it. Sample xml:
<?xml version="1.0" encoding="utf-8"?>
<posts>
<row Id="1" PostTypeId="1" AcceptedAnswerId="26" CreationDate="2010-07-07T19:06:25.043" Score="10" ViewCount="1192" Body="<p>Now that the Engineer update has come, there will be lots of Engineers building up everywhere. How should this best be handled?</p>
" OwnerUserId="11" LastEditorUserId="56" LastEditorDisplayName="" LastEditDate="2010-08-27T22:38:43.840" LastActivityDate="2010-08-27T22:38:43.840" Title="In Team Fortress 2, what is a good strategy to deal with lots of engineers turtling on the other team?" Tags="<strategy><team-fortress-2><tactics>" AnswerCount="5" CommentCount="7" />
<row Id="2" PostTypeId="1" AcceptedAnswerId="184" CreationDate="2010-07-07T19:07:58.427" Score="5" ViewCount="469" Body="<p>I know I can create a Warp Gate and teleport to Pylons, but I have no idea how to make Warp Prisms or know if there's any other unit capable of transporting.</p>
<p>I would in particular like this to built remote bases in 1v1</p>
" OwnerUserId="10" LastEditorUserId="68" LastEditorDisplayName="" LastEditDate="2010-07-08T00:16:46.013" LastActivityDate="2010-07-08T00:21:13.163" Title="What protoss unit can transport others?" Tags="<starcraft-2><how-to><protoss>" AnswerCount="3" CommentCount="2" />
<row Id="3" PostTypeId="1" AcceptedAnswerId="56" CreationDate="2010-07-07T19:09:46.317" Score="7" ViewCount="356" Body="<p>Steam won't let me have two instances running with the same user logged in.</p>
<p>Does that mean I cannot run a dedicated server on a PC (for example, for Left 4 Dead 2) <em>and</em> play from another machine?</p>
<p>Is there a way to run the dedicated server without running steam? Is there a configuration option I'm missing?</p>
" OwnerUserId="14" LastActivityDate="2010-07-07T19:27:04.777" Title="How can I run a dedicated server from steam?" Tags="<steam><left-4-dead-2><dedicated-server><account>" AnswerCount="1" />
<row Id="4" PostTypeId="1" AcceptedAnswerId="14" CreationDate="2010-07-07T19:11:05.640" Score="10" ViewCount="201" Body="<p>When I get to the insult sword-fighting stage of The Secret of Monkey Island, do I have to learn every single insult and comeback in order to beat the Sword Master?</p>
" OwnerUserId="17" LastEditorUserId="17" LastEditorDisplayName="" LastEditDate="2010-07-08T21:25:04.787" LastActivityDate="2010-07-08T21:25:04.787" Title="Do I have to learn all of the insults and comebacks to be able to advance in The Secret of Monkey Island?" Tags="<monkey-island><adventure>" AnswerCount="3" CommentCount="2" />
I would like to parse this xml, but only load certain attributes of the xml, which are Id, PostTypeId, AcceptedAnswerId and other 2 attributes. Is there a way in SAX so that it only loads these attributes?? If there is then how? I am pretty new to SAX, so some guidance would help.
Otherwise loading the whole thing would just be purely slow and some of the attributes won't be used anyways so it's useless.
One other question is that would it be possible to jump to a particular row that has a row Id X? If possible then how do I do this?
"StartElement" Sax Event permits to process a single XML ELement.
In java code you must implement this method
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
if("row".equals(localName)) {
//this code is executed for every xml element "row"
String id = attributes.getValue("id");
String PostTypeId = attributes.getValue("PostTypeId");
String AcceptedAnswerId = attributes.getValue("AcceptedAnswerId");
//others two
// you have your att values for an "row" element
}
}
For every element, you can access:
Namespace URI
XML QName
XML LocalName
Map of attributes, here you can extract your two attributes...
see ContentHandler Implementation for specific deatils.
bye
UPDATED: improved prevous snippet.
It is pretty much the same approach as I've answered here already.
Scroll down to the org.xml.sax Implementation part. You'll only need a custom handler.
Yes, you can override methods that process only the elements you want:
http://www.javacommerce.com/displaypage.jsp?name=saxparser1.sql&id=18232
http://www.java2s.com/Code/Java/XML/SAXDemo.htm
SAX doesn't "load" elements. It informs your application of the start and end of each element, and it's entirely up to your application to decide which elements it takes any notice of.

Categories