Build the XML Document object using JDBC ResultSet - java

We are getting Cursor in JDBC ResultSet object.Now i have to build the complex XML document object using ResultSet. Currently i have been building document object in procedural way.
Now is there any Object oriented way to simplify the xml document building logic.so that it can accommodate the future changes also.
I have following structure of xml document,
<Response>
<BillingInformation>
<BillingID>
<Identifier>
</Identifier>
</BillingID>
<BillInfo>
<ID>
<Identifier>
</Identifier>
</ID>
<BillingCustomerName>
</BillingCustomerName>
<AlternateID>
<Identifier>
</Identifier>
<Type>
</Type>
</AlternateID>
<PostalAddress>
<ID>
<Identifier>
</Identifier>
<Type>
</Type>
</ID>
<StreetAddress>
<AddressContent>
</AddressContent>
<AddressContent>
</AddressContent>
</StreetAddress>
<City>
</City>
<State>
</State>
<Country>
</Country>
<Zip>
</Zip>
<Status>
</Status>
</PostalAddress>
<Contact>
<ContactId>
<Identifier>
</Identifier>
<Type>
</Type>
</ContactId>
<AlternateContactId>
<Identifier>
</Identifier>
<Type>
</Type>
</AlternateContactId>
<ContactName>
<FirstLastName>
<FirstName>
</FirstName>
<LastName>
</LastName>
</FirstLastName>
</ContactName>
</Contact>
<Status>
</Status>
</BillInfo>
</BillingInformation>
</Response>
Any help is appreciated.

I've used the WebRowSet Class to accomplish this in the past.
http://docs.oracle.com/javase/1.5.0/docs/api/javax/sql/rowset/WebRowSet.html
You might find it the easiest approach

Use JPA and JAXB. With JPA you will read (map) DB records into BillingInformation Java object(s), then marshal it to XML with JAXB.

XStream allow to map Objects to XML.
You have to create a Object hierarchy like your XML and anotate the classes with node names.
Works well with simple XML structures, as shown here: http://x-stream.github.io/alias-tutorial.html.

Related

Having trouble unmarshalling a WADL

I need to query some endpoints for their WADLs, and test all the endpoints contained in the WADL. I'm using JaxB to unmarshal the WADL into POJOs (tried Jackson too, but got another error).
Here's the beginning of the XML:
<application>
<grammars/>
<resources base="https://gatewaydsapdev1.company.com/v2">
<resource path="/contents">
<resource path="/labels">
<method name="GET">
<request>
<param name="include" style="query" type="string"/>
<param name="q" style="query" type="string"/>
<param name="offset" style="query" type="string"/>
<param name="limit" style="query" type="string"/>
<param name="flush" style="query" type="boolean"/>
</request>
<response>
<representation element="Response" mediaType="application/json;charset=utf-8"/>
</response>
</method>
</resource>
....
And here's the unmarshalling code:
JAXBContext jaxbContext = JAXBContext.newInstance(WadlApplication.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(xml);
WadlApplication application = (WadlApplication) unmarshaller.unmarshal(reader);
But I get this exception:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"application"). Expected elements are <{http://wadl.dev.java.net/2009/02}application>,<{http://wadl.dev.java.net/2009/02}doc>,<{http://wadl.dev.java.net/2009/02}grammars>,<{http://wadl.dev.java.net/2009/02}include>,<{http://wadl.dev.java.net/2009/02}link>,<{http://wadl.dev.java.net/2009/02}method>,<{http://wadl.dev.java.net/2009/02}option>,<{http://wadl.dev.java.net/2009/02}param>,<{http://wadl.dev.java.net/2009/02}representation>,<{http://wadl.dev.java.net/2009/02}request>,<{http://wadl.dev.java.net/2009/02}resource>,<{http://wadl.dev.java.net/2009/02}resource_type>,<{http://wadl.dev.java.net/2009/02}resources>,<{http://wadl.dev.java.net/2009/02}response>
I don't know how to give the ObjectFactory the data it says is missing. Does anyone have any suggestions? TIA!
Your XML does not have a namespace whereas your JAXB classes do have the namespace http://wadl.dev.java.net/2009/02.
Either add namespace to the XML or drop it from your JAXB classes.

Split XML file with XSLT 2.0 based on element count

Huge XML with the following structure :
<?xml version="1.0" encoding="UTF-8"?>
<productall>
<product type="electronics" date="1-1-2016">
<type name"Androidbased">
<product> InStock </product>
</type>
</product>
<product type="cloths" date="1-12-2008">
<type name"Jeans">
<product> InStock </product>
</type>
</product>
<product type="bags" date="1-12-2008">
<type name"FF">
<product> InStock </product>
</type>
</product>
</productall>
each product type has thousands of records for example electronics are 2000 records and cloths are 8000 records.
I want to split this XML file into multiple XMLs with 1000 records each regardless the type!
I have used XSLT 2.0 based on java & saxon 9 to split it but it doesn't work as it should here is what I did so far :
java -jar sax.jar productall.xml split.xslt
Split.xslt
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="productall" select="1000"></xsl:param>
<xsl:template match="/productall/product[#type]">
<xsl:for-each-group select="product" group-adjacent="(position()-1) idiv $productall">
<xsl:result-document href="part.{current-grouping-key()}.xml">
<productall>
<xsl:copy-of select="current-group()"></xsl:copy-of>
</productall>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
The result is printed out on the terminal screen without XML format and no .XML files are generated. Don't know what is wrong the command syntax or the contents of the XSLT file?
The main problem here is your template matches a product element, which means when you do the xsl:for-each-group, you will be positioned on the product element. Then you are selecting product elements, ye the these are not children of the current element, but of the type elements. So, you need to do this...
<xsl:for-each-group select="type/product" group-adjacent="(position()-1) idiv $productall">
However, you say you want multiple XMLs with 1000 records each regardless the type, but the current XSLT does this for each main product separately, meaning you will get duplicate file names.
Perhaps you should include the main product type in the file name?
<result-document href="part.{../../#type}.{current-grouping-key()}.xml">
Or if you really did want to do it regardless of main product type, you should change your main template to match productall instead.
Try this XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="productall" select="1000"></xsl:param>
<xsl:template match="/productall">
<xsl:for-each-group select="product/type/product" group-adjacent="(position()-1) idiv $productall">
<xsl:result-document href="part.{current-grouping-key()}.xml">
<productall>
<xsl:copy-of select="current-group()"></xsl:copy-of>
</productall>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
I think you simply need to change match="/productall/product[#type]" to match="/productall".

Generate source files from XML

I have the XML file which starts like this:
<?xml version="1.0" encoding="UTF-8"?>
<interface name="AccountAPING" owner="BDP" version="1.0.0" date="now()" namespace="com.betfair.account.api"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<description>Account API-NG</description>
...
afterward there are various blocks, such as:
<operation name="getDeveloperAppKeys" since="1.0.0">
<description>
Get all application keys owned by the given developer/vendor
</description>
<parameters>
<request/>
<simpleResponse type="list(DeveloperApp)">
<description>
A list of application keys owned by the given developer/vendor
</description>
</simpleResponse>
<exceptions>
<exception type="AccountAPINGException">
<description>Generic exception that is thrown if this operation fails for any reason.</description>
</exception>
</exceptions>
</parameters>
</operation>
........
<simpleType name="Status" type="string">
<validValues>
<value name="SUCCESS">
<description>Sucess status</description>
</value>
</validValues>
</simpleType>
........
<dataType name="TimeRange">
<description>TimeRange</description>
<parameter name="from" type="dateTime" mandatory="false">
<description>from, format: ISO 8601)</description>
</parameter>
<parameter name="to" type="dateTime" mandatory="false">
<description>to, format: ISO 8601</description>
</parameter>
</dataType>
How can I generate Java code from this using maven? I tried using "maven-jaxb2-plugin", but it can't parse this structure.
Please note
This is an XML file not not an xsd
I'm using Netbeans
First of all, you need the schema (xsd) that describes your xml sample. Without that schema you can not use Jaxb. You don't have a schema for the sample you shown xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" is not the schema for your xml.
You can use free on-line tools to generate schemas from xml, but you can't rely on this tools without review the automated schema.
To generate Java code from a schema file use XJC, see here. Open a command prompt to the folder where you put your xsd file, and then generate java code you'll just need to type:
$ xjc nameOfSchemaFile.xsd
xjc is included with Java SDK.

XML file to database table + model class generator

I have a requirement which is as follows. Lets say I have a XML file which contains the following content.
<?xml version="1.0"?>
<items>
<item id="1" class="Company" interface="true">
</item>
<item id="2" class="MyCompany" implements="Company">
<attribute name="name" value="CompanyB"/>
<attribute name="vatNumber" value="5678"/>
<reference name="CEO" ref_id="11"/>
<reference name="address" ref_id="19"/>
<collection name="contractors">
<reference ref_id="4"/>
<reference ref_id="3"/>
</collection>
<collection name="departments">
<reference ref_id="7"/>
<reference ref_id="6"/>
</collection>
<collection name="oldContracts">
<reference ref_id="4"/>
<reference ref_id="3"/>
</collection>
<collection name="secretarys">
<reference ref_id="14"/>
<reference ref_id="15"/>
</collection>
</item>
</items>
I want to have a convertor to convert this items file into database tables directly and on the same time generate model classes for each type of items. So than I can have a modelservice to control them .Also when i add more attributes to the type it should be able to update the database table and the model code automatically.
In more better way I require some kind of model code generator which create database tables and maps them both in a well planned manner ?
Is some kind of tool already avaiable to do this type of buisness logic.??? I don't like to reinvent the wheel again.?
I'd suggest you you to develop code that transforms your XML to Hibernate HBM file. Then use Hibernate as a persistence layer.
You can even probably create XSLT transformation from your format to HBM.
Actually after little googling I came across Apache Torque which looks awesome from my needs.

xpath based on condition in java

I have an xml of the following structure:
<Root>
<Sample>
<Materil material_class="book" />
<Book Name="harry" Price="8" />
<Book Name="small things" Price="9" />
<Book Name="snow" Price="10" />
</Sample>
<Commodity>
<Sample>
<Materil material_class="sub" />
<Book Name="sherin" Price="8" />
<Book Name="bigthings" Price="9" />
<Book Name="leopard" Price="10" />
</Sample>
<Commodity>
<Sample>
<Materil material_class="sub" />
<Book Name="azxcv" Price="86" />
<Book Name="ddddd" Price="79" />
<Book Name="qwert" Price="810" />
</Sample>
</Commodity>
<Commodity>
<Sample>
<Materil material_class="subtwo" />
<Book Name="ratnam" Price="86" />
<Book Name="shantharam" Price="99" />
<Book Name="da vinci" Price="10" />
</Sample>
</Commodity>
</Commodity>
</Root>
Is there a way to iterate this xml based on condition like,if the material_class = "sub", iterate the Book tag below that and store the #Name and #Price . If the material_class = "book", iterate the Book tag below that. Also i want to get the length of number of /Root/Commodity/Commodity tags (in this case , it is two). Any help is appreciated. I am new to XPath.
To get the Book #Name and #Price for #material_class='sub' or #material_class='book', use this XPATH
/Root[descendant-or-self::Sample or Sample[descendant-or-self::*]]//*[Materil[#material_class='sub' or #material_class='book']]/Book
OR
//Sample[Materil[#material_class='book' or #material_class='sub']]/Book
After loading this XPATH, to print the Name use #Name and Price use #Price
To get the length of number of /Root/Commodity/Commodity tags, XPATH is
/Root/Commodity/Commodity
OR
//Commodity/Commodity
JAVA:
NodeList node = (NodeList) xpath.evaluate("/Root/Commodity/Commodity", xml, XPathConstants.NODESET);
count = node.getLength(); // OUTPUTS: 2
For your information, actually rendering XML through XSLT is much better performance and easier to implement.
<xsl:apply-templates select="//Sample[Materil[#material_class='sub']]/Book"/>
<xsl:apply-templates select="//Sample[Materil[#material_class='book']]/Book"/>
I do not have access to an XSL editor right now, so have not tested the above, but it will give you an idea. Select the Book, and constrain the Materil with the condition you want.

Categories