JAXB - Example of following a keyref when unmarshalling - java

According to this, you can make use of xs:key and xs:keyref when marshalling and unmarshalling data in JAXB 2.x.
However, I can't find a working example of this being done anywhere.
What we're doing is setting a lookup section in each XML message containing the details for the reference/code values (id, name, description, etc), and then have the data elements later in the message refer back to these items using their key. XML schema defines and supports this through xs:keyref and xs:key (xs:IDREF is not an allowed option).
What I'd like to do is have my JAXB unmarshaller follow these refs dynamically, replacing the key with the referenced object.
Could anybody refer me to an example of this being done?

Are you talking about a compound key situtation?
<directory>
<employee>
<eID>123</eID>
<country>CA</country>
</employee>
<employee>
<eID>123</eID>
<country>US</country>
</employee>
<employee>
<eID>456</eID>
<country>US</country>
</employee>
<phone-number>
<contact eID="123" country="US"/>
</phone-number>
</directory>
If so EclipseLink JAXB (MOXy) could be used:
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/JPA/CompoundPrimaryKeys

Related

Parse XML in which tag name is not fixed

It is easy to parse XML in which tags name are fixed. In XStream, we can simply use #XStreamAlias("tagname") annotation. But how to parse XML in which tag name is not fixed. Suppose I have following XML :
<result>
<result1>
<fixed1> ... </fixed1>
<fixed2> ... </fixed2>
</result1>
<result2>
<item>
<America>
<name> America </name>
<language> English </language>
</America>
</item>
<item>
<Spain>
<name> Spain </name>
<language> Spanish </language>
</Spain>
</item>
</result2>
</result>
Tag names America and Spain are not fixed and sometimes I may get other tag names like Germany, India, etc.
How to define pojo for tag result2 in such case? Is there a way to tell XStream to accept anything as alias name if tag name is not known before-hand?
if it is ok for you to get the tag from inside the tag itself (field 'name'), using Xpath, you can do:
//result2/*/name/text()
another option could be to use the whole element, like:
//result2/*
or also:
//result2/*/name()
Some technologies (specifically, data binding approaches) are optimized for handling XML whose structure is known at compile time. Others (like DOM and other DOM-like tree models - JDOM, XOM etc) are designed for handling XML whose structure is not known in advance. Use the tool for the job.
XSLT and XQuery try to blend both. In their schema-aware form, they can take advantage of static structure information when it is available. But more usually they are run in "untyped" mode, where there is no a-priori knowledge of element names or structure, and everything is handled as it comes. The XSLT rule-based processing paradigm is particularly well suited to "semi-structured" XML whose content is unpredictable or variable.

Can I get to an index of parsed XML using XStream

I am using XStream library for XML parsing. I was wondering if the library allows jumping to a particular node directly using the index.
So for e.g.
<details>
<personal>
<basicInfo>
<firstName>John</firstName>
<lastName>Doe</lastName>
<phoneNumber>9999999999</phoneNumber>
<dateOfBirth>1990-01-01</dateOfBirth>
</basicInfo>
<address>
<street>random St.</street>
<city>City</city>
<stateProv>BC</stateProv>
<country>CA</country>
<postCode>12345</postCode>
</address>
</personal>
<personal>
<basicInfo>
<firstName>John2</firstName>
<lastName>Doe2</lastName>
<phoneNumber>9999999999</phoneNumber>
<dateOfBirth>1990-01-01</dateOfBirth>
</basicInfo>
<address>
<street>random St.2</street>
<city>City2</city>
<stateProv>BC2</stateProv>
<country>CA2</country>
<postCode>12345</postCode>
</address>
</personal>
</details>
For the XML above I would like to skip the first <personal>...</personal>
and only process the second node. Can I call it using an index.
XStream is a simple library to serialize objects to XML and back again.
I am not sure what you mean by process in this context, but if your POJO for serialization is set up correctly to contain a List of "personal" nodes. I don't see why you couldn't deserialize the XML and remove the unwanted node after the fact.
As far as I know, vtd-xml is the only XML parsing routine that natively offers indexing feature, called vtd+XML.

Append data after root element without loading the whole XML file into memory

I have to output an XML file which can contain use amount of data, I am using DOM parser to write XML file. It is also possible to append data to an existing XML file.
My requirement is add data to the root element.
Is it possible to append data without reading the entire XML document (Not to load XML into memory)?
Example Data:
Current XML file:
<employees>
<employee>
<name>jon</name>
<age> 22</age>
<address> address1 </address>
</employee>
</employees>
Required file:
<employees>
<employee>
<name>jon</name>
<age> 22</age>
<address> address1 </address>
</employee>
<employee>
<name>jon1</name>
<age> 24</age>
<address> address2 </address>
</employee>
</employees>
It would be hard if you don't want to load entire XML into memory.
You can achieve this by manipulating raw String (substring, etc.) - but I don't recommend this.
Or you can try using SAX reader http://www.saxproject.org/apidoc/org/xml/sax/XMLReader.html which enables you to manipulate XMLs "on the go". (I'm sorry, although you can use SAX parsers to process XML without reading its whole content, you cannot edit with it)
EDIT:
On second though you can copy existing XML using SAX parser, and by adding event listener to e.g. root you can add a child. It might be good solution if your concern is memory (big xml file).
You could use DOM4j for doing that.

Is it possible to create an object from XML file using DOM?

I use DOM parser to read data from XML file. I know how to read, modify and write back the data. However, I would like to know if it is possible to create an object from an XML file.
I have an XML file which looks like this:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE people SYSTEM "validator.dtd">
<people>
<student>
<name>John</name>
<course>Computer Technology</course>
<semester>6</semester>
<scheme>E</scheme>
</student>
<student>
<name>Foo</name>
<course>Industrial Electronics</course>
<semester>6</semester>
<scheme>E</scheme>
</student>
</people>
and I would like to make it an objects out of it so I can pass them around. Does a solution exist ?
Yes. This is possible through JAXB (Java API for XML binding)
All JAXB implementations provide a tool called a binding compiler to bind a XML schema in order to generate the corresponding Java classes.
For details refer: http://www.oracle.com/technetwork/articles/javase/index-140168.html#xmp1
You could have a look at XML beans or JAXB libraries. In case you don't have a schema file but have a sample XML file, you could create one using inst2xsd tool of xmlbeans. http://xmlbeans.apache.org/docs/2.0.0/guide/tools.html. This could get you started with the schema.

How can I do type-safe Xpath queries in Java?

I'm currently using JDOM for doing some simple XML parsing, and it seems like nothing's type safe - I had a similar issue with using the built-in Java DOM parser, just with lots more API to wade through.
For example, XPath.selectNodes takes an Object as its argument and returns a raw list, which just feels a little Java 1.1
Are there generic-ized XML and XPath libraries for Java, or is there some reason why it's just not possible to do XPath queries in a type-safe way?
If you're familiar with CSS selectors on HTML, it may be good to know that Jsoup supports XML as well.
Update: OK, that was given the downvote apparently a very controversial answer. It may however end up to be easier and less verbose than Xpath when all you want is to select node values. The Jsoup API is namely very slick. Let's give a bit more concrete example. Assuming that you have a XML file which look like this:
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="1">
<name>John Doe</name>
<age>30</age>
<address>
<street>Main street 1</street>
<city>Los Angeles</city>
</address>
</person>
<person id="2">
<name>Jane Doe</name>
<age>40</age>
<address>
<street>Park Avenue 1</street>
<city>New York</city>
</address>
</person>
</persons>
Then you can traverse it like follows:
Document document = Jsoup.parse(new File("/persons.xml"), "UTF-8");
Element person2 = document.select("person[id=2]").first();
System.out.println(person2.select("name").text());
Elements streets = document.select("street");
for (Element street : streets) {
System.out.println(street.text());
}
which outputs
Jane Doe
Main street 1
Park Avenue 1
Update 2: since Jsoup 1.6.2 which was released March 2012, XML parsing is officially supported by the Jsoup API.
AFAIK all of the xml queries in java are non-typesafe and most are java 1.3 compatible. That said my favorite parser/generator is the xml pull parser (xmlpp) style parser. I believe java has XmlStreamReader and XmlStreamWriter if you're using 1.6 which are almost the same as the xmlpp library. I especially like that I can write a method getFoo that takes a stream reader and pulls from it and returns a Foo object. It's sort of the best between DOM and SAX. I think it may be referred to as StAX by some.
I'm getting a little ramble-y so I'm quitting now

Categories

Resources