Mule iterate over xpath result - java

I've set the following xml as payload in order to iterate over every product using splitter component.
<root>
<product>
<id>1</id>
<name>apple</name>
</product>
<product>
<id>2</id>
<name>orange</name>
</product>
</root>
<splitter expression="#[xpath('//product')]" />
The splitter component returns an object of type org.dom4j.tree.DefaultElement on which I call the method asXML() to get single product's xml.
First iteration
<product>
<id>1</id>
<name>apple</name>
</product>
Second iteration
<product>
<id>2</id>
<name>orange</name>
</product>
I need to replace splitter with foreach component, but I'm having some troubles.
<foreach collection="#[xpath('//product')]">
...
</foreach>
The foreach component returns an object of type org.apache.xerces.dom.ElementNSImpl which hasn't the method asXML().
Any idea how I can get products'xml as String as explained in the first example?
Thanks in advice!

Use Mule's dom-to-xml-transformer.
Reference: http://www.mulesoft.org/documentation/display/current/DomToXml+Transformer

Related

JSON to XML with type attribute in java

I'm rewriting C# application into java code.
There is REST API which return jsons.
I have to parse json to XML but C# library and Java doing it in difference ways.
How to keep type= attribute in java? I can't use JAXB annotations becouse there are too many objects in response and they might changing. XML.toString(jsonObject) doesn't work for me.
C# parsing is done in this way:
XDocument.load(JsonReaderWriterFactory.CreateJsonReader(Encoding.ASCII.GetBytes(jsonString), new XmlDictionaryReaderQuotas()));
C# result:
<root type="object">
<Items type="array">
<item type="object">
<Name type="string">test</Name>
<Total type="number">12.8000000</Total>
<CurrencyCode type="string">CHF</CurrencyCode>
<Country type="string">CH</Country>
</item>
</Items>
</root>
Java result:
<root>
<Items>
<item>
<Name>test</Name>
<Total>12.8000000</Total>
<CurrencyCode>CHF</CurrencyCode>
<Country>CH</Country>>
</item>
</Items>
</root>
I've used org.w3c.Document and org.w3c.dom.Element and set up attribute "type".
Anyway thanks for help :)

Removing xml tags by using java

I have a very simple xml file that I would like to create a simple function to remove a tag from it. Here is my sample xml file:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channels>
<channel>
<items>
<item>
<title>Java Tutorials></title>
<link>http://www.tutorial-point.com/</link>
</item>
<item>
<title>Java Tutorials></title>
<link>http://www.javatpoint.com/</link>
</item>
</items>
</channel>
</channels>
</rss>
In my Java program, simply want to call a method to delete two tags from the file. I'm not very familiar with XML but did manage to create a reader and writer but now I'm having trouble creating a method to delete an item from my file.
// retrieve the element
Element element = (Element) doc.getElementsByTagName("channels").item(0);
Element element2 = (Element) doc.getElementsByTagName("channel").item(0);
// remove the specific node
element.getParentNode().removeChild(element);
element2.getParentNode().removeChild(element2);
When I used the above code in Java, it removed all the tags but I expected the result like below:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<items>
<item>
<title>Java Tutorials></title>
<link>http://www.tutorial-point.com/</link>
</item>
<item>
<title>Java Tutorials></title>
<link>http://www.javatpoint.com/</link>
</item>
</items>
</rss>
Can you please suggest?
Try this.
Element rss = (Element) doc.getElementsByTagName("rss").item(0);
Element channels = (Element) doc.getElementsByTagName("channels").item(0);
Element items = (Element) doc.getElementsByTagName("items").item(0);
rss.appendChild(items);
rss.removeChild(channels);

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".

How to get values from child nodes using java?

I have a XML content like below...
<Parent_Tag>
<Parent_Tag_1>
<Component>
<Type>ABC</Type>
<Amount>
<Value_1>0.1</Value_1>
<Value_2>AAA</Value_2>
</Amount>
</Component>
</Parent_Tag_1>
<Parent_Tag_2>
<Item>
<Item_1>
<Component>
<Type>CCC</Type>
<Amount>
<Value_1>0.1</Value_1>
<Value_2>BB</Value_2>
</Amount>
</Component>
<Component>
<Type>BBB</Type>
<Amount>
<Value_1>2.0</Value_1>
<Value_2>AA</Value_2>
</Amount>
</Component>
</Item_1>
</Item>
</Parent_Tag_2>
</Parent_Tag>
I need to get the values in tag Component under Parent_Tag_1. But my code gave all the component tags under Parent_Tag. How to fix this ??
Please give a suggestion...

Splitting nested XML with Camel Tokenizer language

I am trying to split following XML with Camel's XMLTokenizer language:
<units>
<unit type="menu">
<id>1</id>
<unit type="submenu">
<id>1</id>
</unit>
</unit>
<unit type="menu">
<id>2</id>
<unit type="submenu">
<id>1</id>
</unit>
</unit>
</units>
My splitter looks like this:
.split().tokenizeXML("unit").streaming()
and my problem is that it is producing splitted XML without end tag like this:
<unit type="menu">
<id>1</id>
<unit type="submenu">
<id>1</id>
</unit>
It would appear that with tokenizeXML() it is not possible to get this working since it will just scan for </unit> end tag. What would be preferred way to handle this case? Is there some other splitting method that would get me the result that I need? I would like to use streaming() so splitting with xpath() is not an option for me.
You can use camel-stax that allows to use the SAX api that supports streaming mode.
http://camel.apache.org/stax
You would need to define a POJO and the JAXB annotations that declares the binding.

Categories