46646

JaxB to read class hierarchy

Just extending Parsing class hierarchy using JaxB question. Want to read following xml file using JaxB

<IMPORT> <TABLE NAME="USER"> <ROW> <USER_ID>1</USER_ID> <ROW_VERSION>1</ROW_VERSION> <USER_NAME>Navnath</USER_NAME> <LOGIN>Navnath</LOGIN> <LOGIN_PASSWORD>Navnath</LOGIN_PASSWORD> </ROW> <ROW> <USER_ID>2</USER_ID> <ROW_VERSION>1</ROW_VERSION> <USER_NAME>Kumbhar</USER_NAME> <LOGIN>Kumbhar</LOGIN> <LOGIN_PASSWORD>Kumbhar</LOGIN_PASSWORD> </ROW> </TABLE> <TABLE NAME="WORK"> <ROW> <WORK_ID>1</WORK_ID> <WORK_NAME>Work1</WORK_NAME> <ROW_VERSION TYPE="N">1</ROW_VERSION> </ROW> <ROW> <WORK_ID>2</WORK_ID> <WORK_NAME>Work2</WORK_NAME> <ROW_VERSION TYPE="N">1</ROW_VERSION> </ROW> </TABLE> <TABLE> ... </TABLE> <TABLE> ... </TABLE> <TABLE> ... </TABLE> </IMPORT>

You can see in above xml file is column names are different in each table. I want to insert this data in database. I try to create class hierarchy for this, But I don't know how to do this. My ROW class will contains diffrent xml element per table and this is the area which I am not able to configure. Please suggest.

Answer1:

<strong>Note:</strong> I'm the <strong>EclipseLink JAXB (MOXy)</strong> lead and a member of the <strong>JAXB (JSR-222)</strong> expert group.

You could leverage MOXy's @XmlDescriminatorNode/@XmlDescriminatorValue extension for this use case (see: http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-moxy-extension.html).

<strong>Import</strong>

import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement(name="IMPORT") @XmlAccessorType(XmlAccessType.FIELD) public class Import { @XmlElement(name="TABLE") private List<Table> tables; }

<strong>Table</strong>

The @XmlDescriminatorNode annotation is used to specify the XML attribute that will be used to indicate which subclass will be instantiated. A JAXB implementation can't pull in the subclasses of a class via reflection, we will use the @XmlSeeAlso annotation to reference them.

import javax.xml.bind.annotation.XmlSeeAlso; import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode; @XmlDiscriminatorNode("@NAME") @XmlSeeAlso({UserTable.class, WorkTable.class}) public abstract class Table { }

<strong>UserTable</strong>

The @XmlDescriminatorValue annotation is used to specify the value of the NAME attribute that corresponds to a particular subclass.

import java.util.List; import javax.xml.bind.annotation.*; import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue; @XmlDiscriminatorValue("USER") @XmlAccessorType(XmlAccessType.FIELD) public class UserTable extends Table { @XmlElement(name="ROW") private List<UserRow> rows; }

<strong>UserRow</strong>

import javax.xml.bind.annotation.XmlElement; public class UserRow { @XmlElement(name="USER_ID") private int userID; @XmlElement(name="USER_NAME") private String userName; }

<strong>WorkTable</strong>

import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue; @XmlDiscriminatorValue("WORK") public class WorkTable extends Table { }

<strong>jaxb.properties</strong>

To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

<strong>Demo</strong>

import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Import.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum15741264/input.xml"); Import result = (Import) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(result, System.out); } }

<strong>input.xml/Output</strong>

Below is the input to and output from running the demo code.

<?xml version="1.0" encoding="UTF-8"?>
<IMPORT>
   <TABLE NAME="USER">
      <ROW>
         <USER_ID>1</USER_ID>
         <USER_NAME>Navnath</USER_NAME>
      </ROW>
      <ROW>
         <USER_ID>2</USER_ID>
         <USER_NAME>Kumbhar</USER_NAME>
      </ROW>
   </TABLE>
   <TABLE NAME="WORK"/>
</IMPORT>


<strong>Alternative Solutions</strong>

Alternatively using only the standard JAXB APIs you could try the following approach using an XmlAdapter

Recommend

  • How do I request a subset of XMLElements using MOXy?
  • How can I alias a default import in Javascript?
  • MessageBodyWriter not found for media type=text/html but works for JSON
  • XML mapping to objects without attributes in C#
  • standalone value does not appear in xml generated by moxy - jaxb
  • JAXB convert multiple attributes to one type while unmarshalling
  • JAXB Map adapter
  • Add animated gifs to react web apps
  • With Eclipselink Moxy How do I map xml content to a name different to value?
  • Want to add a timer to GlassFish Server, don't know where to start
  • jaxb2-maven-plugin generates invalid source for doubles with default value =INF
  • Reading Element attribute value using XStream
  • Use of Multiple Inheritance in EclipseLink MOXy
  • Memory allocation of base class and derived class constructor
  • can jquery implement the class inherit like prototype
  • Complex Maven2 with Flex4 Setup
  • About multiple inheritance and ambiguity
  • Spring RestTemplate slow response time
  • Neo4j cypher query for X-chromosome ancestors
  • What does 'this' mean in a c# constructor? [duplicate]
  • SQL complicated recursive CTE
  • what is side-cast or cross-cast in Dynamic_cast in C++
  • Understanding Intl.DateTimeFormat as a JavaScript object
  • back button function for phonegap windows phone 7
  • Loading .coffee files via a view in Rails
  • NHibernate Validation Localization with S#arp Architecture
  • JSON with duplicate key names losing information when parsed
  • How to make Safari send if-modified-since header?
  • Warning: Can't call setState (or forceUpdate) on an unmounted component
  • How to pass list parameters for each object using Spring MVC?
  • jqPlot EnhancedLegendRenderer plugin does not toggle series for Pie charts
  • How to format a variable of double type
  • bootstrap to use multiple ng-app
  • How to get icons for entities from eclipse?
  • Proper way to use connect-multiparty with express.js?
  • Load html files in TinyMce
  • coudnt use logback because of log4j
  • Setting background image for body element in xhtml (for different monitors and resolutions)
  • Turn off referential integrity in Derby? is it possible?
  • JaxB to read class hierarchy