Win a copy of Machine Learning Systems: Designs that scale this week in the Scala forum
or Xamarin in Action: Creating native cross-platform mobile apps in the Android forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Parsing XML using JAXB  RSS feed

 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm a newbie to Java and XML parsing. As I'm learning I'm trying to work on parsing the below XML (Please Note: I've replaced the namespaces and actual element tags with generic terms since I cannot put the actual XML in here) to later put some validation rules to the element values after I've extracted them.

I came across JAXB and wanted to how I can use it to parse the XML. Basically I want to retrieve the values of all elements within the 'Parent2' tags. I don't want anything inside the 'Parent1' or the 'Exception' tags.

Could someone please provide some guidance as to how I can do it. The examples of unmarshalling from XML which I've come across so far are for simple XML's and not something as complicated as this.

The XML is as below:



Thanks
 
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

Have you found any XML tutorials? Try this section of the Java™ Tutorials.

Moving discussion to our XML forum.
 
Karthik Nagarajan
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Ritchie,

Thanks for the welcome note and for the link. Yes, I did see this link before. Since I'm new to JAXB was trying to see what would be general approach for this. How I can create the class file for my XML (I guess i should declare the @XMLRootElement as 'RootElement' of my XML, then the @XMLElements as the elements of the XML? How do I handle the nested child elements inside each Parent tag?). Then after the class file is created then i can use JAXBContext and Unmarshall the XML to objects?). I came across the below example and I tried executing in Eclipse IDE and it executed successfully. I should follow something along these lines right? Or should i try getting the schema of my XML and then use JAXB to create class file for it and then unmarshall the XML? (the issue is that the schema for my XML is pretty complex and it has reference to many other schemas. so should i put all the schemas under one package and then create the class file?) Please suggest some ideas.

'User' Class file:



JAXBToXML:




JAXBToObject:




Thanks
 
Sheriff
Posts: 23507
47
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Karthik Nagarajan wrote:Since I'm new to JAXB was trying to see what would be general approach for this.



For getting started, I would say the general approach would be to have the elements of your XML match the data items in your Java object. After all, JAXB is intended to work in both directions, from XML to Java and from Java to XML. That would mean that losing information from the XML while mapping it to Java would kind of go against that idea. I don't want to say it's impossible since I'm not a JAXB expert, but I would expect it to be hard to do if it were possible.
 
Karthik Nagarajan
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I was trying to parse the below subset of the above XML.




i wrote the below classes:

RootElement class:




Parent1Child1 class:





Main Unmarshaller class:





When i execute the above i'm getting the below exception. Could you please help/guidance and let me know where the issue is and how I can resolve it.

Exception:

Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://yyyy", local:"RootElement"). Expected elements are <{}parent1child1>,<{}rootElement>
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:254)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:249)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:116)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1049)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:478)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:459)
at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:148)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:211)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:184)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
at com.mysoftkey.jaxb.ParseXML1.main(ParseXML1.java:23)


Thanks
 
Paul Clapham
Sheriff
Posts: 23507
47
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Karthik Nagarajan wrote:Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://yyyy", local:"RootElement"). Expected elements are <{}parent1child1>,<{}rootElement>



If I'm not mistaken, this says "I was expecting a parent1child1 node in no namespace or a rootElement node in no namespace, but instead I found a RootElement node in the http://yyyy namespace."

The main problem I see there is that you didn't tell JAXB what namespace your nodes are in. Looks like you need to specify name and namespace in the annotations. The other minor thing which may or may not be a problem is that there are case discrepancies, "RootElement" versus "rootElement".
 
Karthik Nagarajan
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the above suggestion Paul. I added the name and namespace to the rootElement class. The updated class is as below.

RootElement class:



When i execute the main unmarshalling class now I dont see any errors but the arraylist is empty. The output is blank. Does the unmarshal method not set the values for the elements when the xml is provided as parameter to the method. Could you please help out.
 
Karthik Nagarajan
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also i tried to just test if the marshaller method works for this. I modified the main program as below to run the marshaller method 1st. It is generating the XML but it is not identical to the test1.xml as expected.

Modified Main program:


When i execute the above i get the below XML as output out of the marshaller method:



could you please let me know why 2 instances of parent1child1 tags are getting created, one within the 'Parent1' tag and one outside it. Also why is it that i'm getting the namespace prefixes 'ns3' and 'ns2' in the generated XML.
 
Paul Clapham
Sheriff
Posts: 23507
47
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're getting those namespace prefixes because JAXB needs to specify the namespace for those elements. In XML the choice of namespace prefix is completely arbitrary -- it's the namespace URI which matters, not the prefix. Your original document used the default namespace, which is a variation which declares a namespace URI but doesn't use a prefix. Still the same thing as JAXB's output, though. (I dislike the default namespace because it hides from the human reader the fact that a particular element is actually in a namespace, which can lead to confusion.)

Anyway the official position is that namespace prefixes don't matter, so you shouldn't worry about whatever you get from JAXB. However people quite often don't feel that way, they get attached to the prefixes they chose. So if you do a web search for jaxb namespace prefix you'll find a lot of suggestions about how to get JAXB to use your preferred prefix. (I didn't notice if any of the articles covered the default namespace, but then I only did a quick scan.)
 
Karthik Nagarajan
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for clarifying on the namespaces Paul. Sorry to be persistent with my questions, I'm trying to learn this stuff. Regarding the 'Parent1Child1' tag repeating twice. I commented out the below 2 from the RootElement class.



For simplicity sake i also commented the namespace annotations.

Modified RootElement class:



When i execute the main program for marshalling i get the below result:




If i uncomment the below and run the marshaller i'm getting the 'Parent1Child1' tag repeated twice. Could you please let me know why that would be the case. I should be specifying the 'Parent1Child1' as a XMLElement right?




Result after uncommenting the above:



Finally i'm still not sure why the unmarshaller would not return the parsed values when i provide the 'Textxml1.xml' to the urmarshaller method. Basically nothing is being returned. Could you please let me know where the issue could be.

Thanks
 
Ranch Hand
Posts: 708
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am not going to bring light to any of the doubt you may have along the study. I can't read because I think the presentation of the problem is fundamentally flawed. But I like to let you know that it is not the proper way to do an abstraction of an xml the way you show. Every element has its own indexing as to its positioning in the the node tree. That is generic, it is; but it is not its characteristic premier. Its characteristic premier is its name. Its position in the tree is taken care of by the parser such as our eyes as well as the software parsers. It is the called the documentary order. It would be unique. But the name, it is not at all unique. parent1child1, parent1child2 as names are rendering all names unique (in fact a way of saying the position in the documentary order is unique - it does not help to saying that twice and it is redundant). A schema's construction will be reflecting the same. If you do parent1child1, parent1child2, the schema would be radically different for pt->(x,y) as <pt><x>...</x><y>...</y></pt> from pt->(x,x) as <pt><x>...</x><x>...</x></pt>. In schema, they are radically different. In jaxb, the same generically different. Hence, if you want to investigate what jaxb will do for you and/or how to make a schema out of an instance of xml, you should change the way you make abstraction of it. It will confuse the machine as well as yourself because the information so abstracted out is not the right information one needs.
 
That which doesn't kill us makes us stronger. I think a piece of pie wouldn't kill me. Tiny ad:
Rocket Oven Kickstarter - from the trailboss
https://coderanch.com/t/695773/Rocket-Oven-Kickstarter-trailboss
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!