Tuesday, August 27, 2013

Dynamic XML Transformation in JAVA


I couldn't find one decent library in Java which transforms XMLs using XPath mappings. There are several stack over flow threads thread1,thread2 ended up using either XSLT or any Object mapping frameworks.So i've developed a basic utility class which accomplishes this task without using  any third party libraries .

Requirement:

      Need to form Target XML as shown below given Source XML & XPath mappings.
     













Constraints : No XSLT,No XSD, No JAXB


Solution:

  Complete code is available in my github repository,  feel free to fork it to contribute :). Complete transformation can be by following these 3 steps.

 Step 1: Converting generic XPaths to Complete XPaths


    Input of this step is a Map of generic XPaths as shown,
 /TargetOrder/OrderId = /SourceOrder/@id  
 /TargetOrder/TargetOrderDate = /SourceOrder/SourceOrderDate  
 /TargetOrder/TargetItems/Item[a]/@id = /SourceOrder/SourceItems/SourceItem[a]/@id  
 /TargetOrder/TargetItems/Item[a]/@desc = /SourceOrder/SourceItems/SourceItem[a]/ItemDesc  

To get the complete XPaths we need to run source XPaths against the source XML so that array size etc.. cab be identified. This complete  operation is done in the method generateCompleteXpaths() of class DynamicXMLTransformer.java. Final Map after going through this phase looks like,

 /TargetOrder/TargetItems/Item[1]/@desc = Nexus 4  
 /TargetOrder/TargetItems/Item[2]/@desc = Nexus 10  
 /TargetOrder/TargetItems/Item[1]/@id = 1111111  
 /TargetOrder/TargetItems/Item[2]/@id = 222222  
 /TargetOrder/TargetOrderDate = 2013-08-27T11:00:00  
 /TargetOrder/TargetItems/Item[1]/Taxes/Tax[1]/@type = SalesTax  


 Step 2: Generation of Target DOM based on previous step XPaths


      Only tricky part of this algorithm is to generate target DOM based on the target XPaths.
      This operation is done in the method createTargetDocument().This achieved just iterating
      individual  XPaths and creating childNodes under the parent elements.

Step 3: Populating Target DOM with values from the Map


         Once target DOM is ready we will fire XPath on it and get the NodeList, based on the Node
          type if  it is  an attribute we will call .setNodeValue() & if it is Element call .setTextContent()
          as shown,

  if (nodes.item(0) instanceof Attr) {  
     ((Attr) nodes.item(0)).setNodeValue(value);  
    } else if (nodes.item(0) instanceof Element) {  
     ((Element) nodes.item(0)).setTextContent(value);  
    }  

Thats it convert this target DOM to String and you are ready to go :) :)

For running complete code fork the git repository
(https://github.com/TheGanesh/DynamicXMLTransformer) & run the main method in the Main.java.

Happy coding .....


Thank you,
Ganesh Kandisa,
kandisa.ganesh@gmail.com