Camel aggregation of XMLs based on the value of XML elements - java

I have the following XMLs:
XML1:
<Person>
<Name>Ben</Name>
<Adress>1234</Address>
</Person>
XML2:
<Person>
<Name>Johnson</Name>
<Adress>5678</Address>
</Person>
XML3:
<Person>
<Name>Harry</Name>
<Adress>1234</Address>
</Person>
I want to aggregate the XMLs only if the attribute value of the Address element is the same, so in this case XML1 and XML3 will be aggregated to look like:
<Person>
<Name>Ben</Name>
<Adress>1234</Address>
</Person>
<Person>
<Name>Harry</Name>
<Adress>1234</Address>
</Person>
(P.S: Result need not be an XML, can be a string).
Is it possible using Camel ?
from ("direct:x")
..............
.to(output)

This is the approach I will take, In fact I have done it already.
Use a simple processor to aggregate all these XML's to a single XML
Write a XSLT to create your desired XML from the aggregated XML, that way if at all you want to change your logic, you can just do it inside XSLT. XSLT is powerful this way.
I would hesitate to either keep these kind of logic in camel routes or write a pojo to do the job.

Related

Selective XML parsing

This the xml file I have
<?xml version="1.0" encoding="UTF-8"?>
<Bank>
<Account type="saving">
<Id>1001</Id>
<Name>Jack Robinson</Name>
<Amt>10000</Amt>
</Account>
<Account type="current">
<Id>1002</Id>
<Name>Sony Corporation</Name>
<Amt>1000000</Amt>
</Account>
</Bank>
I need to parse this xml and get the contents between <Bank>...</Bank>. My output xml should be
<Account type="saving">
<Id>1001</Id>
<Name>Jack Robinson</Name>
<Amt>10000</Amt>
</Account>
<Account type="current">
<Id>1002</Id>
<Name>Sony Corporation</Name>
<Amt>1000000</Amt>
</Account>
Any ideas on how to achieve this using Java?
First of all:
your output XML is not valid XML.
XML must have root element which you try to remove.
As #Seelenvirtuose said, there are tons of ways to do what you want on many levels.
From simple manipulating original XML as String and up to using DOM model, JAXB, XPath/XQuery, or XSLT. It is matter of your choice.
As example with Apache commons utils:
String resultString = org.apache.commons.lang.StringUtils.substringBetween(originalXMLString,"<Bank>","</Bank>").trim();
Of course your output can be only String, because it is not valid XML. Then you can do with that String whatever you want - print it, store in file or DB etc...

How to map nested XML fields to CSV?

I know how to do this for simple xml like-
<person>
<age>10</age>
<weight>20</weight>
</person>
will be mapped to CSV as-
age,weight
10,20
But how to do it for nested tags?
Example: I have following xml-
<root>
<prop1>someValue</prop>
<prop2>
<innerProp>
<property1>value1</property1>
<property2>
<subProperty1>value2</subProperty1>
<subProperty2>value3</subProperty2>
<subProperty3>value4</subProperty3>
</property2>
<property3>value5</property3>
<property4>value6</property4>
<property5>
<subProperty4>value7</subProperty4>
<subProperty5>value8</subProperty5>
<subProperty6>value9</subProperty6>
</property5>
<property6>value10</property6>
<property7>value11</property>
</innerProp>
</prop2>
</root>
What will be its transformation in CSV?
Or this can't be done at all?
You could flatten this by using a dot for each indent you see. This would be the outcome:
prop1, prop2.innerProp.property1, prop2.innerProp.property2.subProperty1, prop2.innerProp.property2.subProperty2, ...

Can I get to an index of parsed XML using XStream

I am using XStream library for XML parsing. I was wondering if the library allows jumping to a particular node directly using the index.
So for e.g.
<details>
<personal>
<basicInfo>
<firstName>John</firstName>
<lastName>Doe</lastName>
<phoneNumber>9999999999</phoneNumber>
<dateOfBirth>1990-01-01</dateOfBirth>
</basicInfo>
<address>
<street>random St.</street>
<city>City</city>
<stateProv>BC</stateProv>
<country>CA</country>
<postCode>12345</postCode>
</address>
</personal>
<personal>
<basicInfo>
<firstName>John2</firstName>
<lastName>Doe2</lastName>
<phoneNumber>9999999999</phoneNumber>
<dateOfBirth>1990-01-01</dateOfBirth>
</basicInfo>
<address>
<street>random St.2</street>
<city>City2</city>
<stateProv>BC2</stateProv>
<country>CA2</country>
<postCode>12345</postCode>
</address>
</personal>
</details>
For the XML above I would like to skip the first <personal>...</personal>
and only process the second node. Can I call it using an index.
XStream is a simple library to serialize objects to XML and back again.
I am not sure what you mean by process in this context, but if your POJO for serialization is set up correctly to contain a List of "personal" nodes. I don't see why you couldn't deserialize the XML and remove the unwanted node after the fact.
As far as I know, vtd-xml is the only XML parsing routine that natively offers indexing feature, called vtd+XML.

Append data after root element without loading the whole XML file into memory

I have to output an XML file which can contain use amount of data, I am using DOM parser to write XML file. It is also possible to append data to an existing XML file.
My requirement is add data to the root element.
Is it possible to append data without reading the entire XML document (Not to load XML into memory)?
Example Data:
Current XML file:
<employees>
<employee>
<name>jon</name>
<age> 22</age>
<address> address1 </address>
</employee>
</employees>
Required file:
<employees>
<employee>
<name>jon</name>
<age> 22</age>
<address> address1 </address>
</employee>
<employee>
<name>jon1</name>
<age> 24</age>
<address> address2 </address>
</employee>
</employees>
It would be hard if you don't want to load entire XML into memory.
You can achieve this by manipulating raw String (substring, etc.) - but I don't recommend this.
Or you can try using SAX reader http://www.saxproject.org/apidoc/org/xml/sax/XMLReader.html which enables you to manipulate XMLs "on the go". (I'm sorry, although you can use SAX parsers to process XML without reading its whole content, you cannot edit with it)
EDIT:
On second though you can copy existing XML using SAX parser, and by adding event listener to e.g. root you can add a child. It might be good solution if your concern is memory (big xml file).
You could use DOM4j for doing that.

How to add multiple attribute values to xml file in JAVA using DOM

I have One XML Like
<root>
<name id="1">Abc</name>
<salary>25000</salary>
</root>
I want something like this
<root>
<name id="1,2">Abc</name>
<salary>25000</salary>
</root>
I am able to create the attribute by using DOM parser as:
Document doc = _docBuilder.newDocument();`
Attr attr = doc.createAttribute("id");
attr.setValue("1");
name.setAttributeNode(attr);
How can I get multiple attribute values for the same attribute.
XML does not support attributes with multiple values.
You could certainly do: attr.setValue("1,2");
However that really isn't very XML friendly. Also, you probably shouldn't have more than one value for an id. You may wish to consider something like this:
<thing>
<name>Abc</name>
<reference_ids>
<id>1</id>
<id>2</id>
</reference_ids>
</thing>

Categories

Resources