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,
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/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.
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,
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
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