Reading one specific element in a xml payload - java

I'm trying to read information from a specific element, here is my xml payload :
<?xml version="1.0"?>
<tns:createTicket xmlns:tns="">
<contact>
<gender>F</gender>
<firstname>ANNE</firstname>
<lastname>MP</lastname>
<phone>88</phone>
</contact>
<issue>
<occurrenceDate>2020-03-23T00:01:00+01:00</occurrenceDate>
<location>
<streetName1>Rpp</streetName1>
<zipCode>999999</zipCode>
<city>AMMM</city>
<countryCode>FR</countryCode>
</location>
<typeCode>GAM</typeCode>
<otherInformations>
<name>Ser</name>
<value>Two</value>
</otherInformations>
<otherInformations>
<name>deliveryAddress</name>
<value>RURU</value>
</otherInformations>
**<otherInformations>
<name>**serDat**</name>
<value>**2020-03-23**</value>
</otherInformations>**
<otherInformations>
<name>gracias</name>
<value>False</value>
</otherInformations>
</issue>
</tns:createTicket>
How can I read the informations from this specific element from the payload :
serDat
2020-03-23
I use the Dom librairy in my code but I'm only able to read the informations from the first 'otherinformations' element and not the other one. I don't have this problem when I want to read the informations from an unique element in the XML payload.
EDIT: I've tried the xPath Librairy
var factory = DocumentBuilderFactory.newInstance()
var builder = factory.newDocumentBuilder()
var document = builder.parse(new InputSource(new StringReader(payload)));
//var rootElement = document.getDocumentElement()
var xpf = XPathFactory.newInstance()
var xpath = xpf.newXPath()
print(payload)
var nodes = xpath.evaluate("/createTicketRequest/payload/issue/otherInformations", document, XPathConstants.NODESET) as NodeList
for(i in 0..nodes.getLength()) {
print(nodes.item(i).getNodeValue());
}
But the result of print(nodes.item(i).getNodeValue()); is NULL
Thank you for your help !

Related

How to add new attribute into XML string in JAVA? Condition: based on parent Key and I can use only JAVA internal api if we need to do parse or SAX

I have a following xml string.
<aa>
<bb>
<cc>
<cmd>
<efg sid="C1D7B70D7AF705731B0" mid="C1D7D7AF705731B0" stid="-1" dopt="3">
<pqr>
<dru fo="1" fps="1" nku="WBECDD6CC37656E6C9" tt="1"/>
<dpo drpr="67" dpi="16"/>
<dres >
<dre dreid="BB:8D679D3511D3E4981000E787EC6DE8A4:1:1:0:2:1" fa="1" dpt= "1" o="0"/>
</dres>
</pqr>
</efg>
</cmd>
</cc>
</bb>
</aa>
I need to add "login" attribute inside <efg> tag. So new XML would be
<aa>
<bb>
<cc>
<cmd>
<efg sid="C1D7B70D7AF705731B0" login="sdf34234dfs" mid="C1D7D7AF705731B0" stid="-1" dopt="3">
<pqr>
<dru fo="1" fps="1" nku="WBECDD6CC37656E6C9" tt="1"/>
<dpo drpr="67" dpi="16"/>
<dres >
<dre dreid="BB:8D679D3511D3E4981000E787EC6DE8A4:1:1:0:2:1" fa="1" dpt= "1" o="0"/>
</dres>
</pqr>
</efg>
</cmd>
</cc>
</bb>
</aa>
Condition is:
I can only use inbuilt Java API (java 8) or SAX parser or xmlbuilder
Add condition is based on Parent tag i.e need to check <cmd> then in child need to add <login> because it is not sure always that <efg> tag would always be there with the same name, it could be with any name.
I have tried with DOM parser with following code.
String xml = "xmlString";
//Use method to convert XML string content to XML Document object
Document doc = convertStringToXML( xml );
doc.getDocumentElement().normalize();
Node m = doc.getElementsByTagName("cmd").item(0).getFirstChild();
Attr login = doc.createAttribute("login");
login.setValue("123567");
m.appendChild(login);
However, I am getting following error in my last line of code.
Exception in thread "main" org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
Please anyone suggest me, how to add new attribute login into based on my condition no 2.
NodeList nodeList = doc.getElementsByTagName("cmd");
//Check <cmd> tag is present and then check <cmd> tag has child nodes
if (nodeList != null && nodeList.item(0).hasChildNodes()) {
//Get first child node of <cmd> xml tag
String nodeName = doc.getElementsByTagName("cmd").item(0).getFirstChild().getNodeName();
NodeList childNodeList = doc.getElementsByTagName(nodeName);
Element el = (Element) childNodeList.item(0);
//set pgd_login attribute with respective value
el.setAttribute("login", "xyz");
//Convert back into xml string from Document
xml = XMLHelpers.TransformDOMDocumentToString(doc);
}

XML Merging using XPATH

I am trying to merge two xml using
"javax.xml.xpath.XPath".
Both source and destination xml looks as below mentioned.
i want to append all the nodes of "bpmn:process" in the second xml to first xml
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn:collaboration id="Collaboration_1ah989h">
<bpmn:participant id="Participant_108if28" processRef="Process_2" />
</bpmn:collaboration>
<bpmn:process id="Process_1" isExecutable="false">**
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_1i0zw0x</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:intermediateThrowEvent id="IntermediateThrowEvent_00epl00">
<bpmn:incoming>SequenceFlow_1i0zw0x</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_05qx4z2</bpmn:outgoing>
</bpmn:intermediateThrowEvent>
</bpmn:process>
</bpmn:definitions>
Below is the code used to merge xml
Document destination= (Document) xpath.evaluate("/", new InputSource("C:/diagram_Sec.bpmn"), XPathConstants.NODE);
NodeList listPosts = (NodeList) xpath.evaluate("//bpmn:process//*",new InputSource("C:/diagram_Fir.xml"), XPathConstants.NODESET);
Element element= (Element) xpath.evaluate("//bpmn:process", destination, XPathConstants.NODE);
for (int i = 0; i < listPosts.getLength(); i++) {
Node listPost = listPosts.item(i);
Element element = (Element) listPost;
AttributeMap map = (AttributeMap) element.getAttributes();
for(int j=0;j<map.getLength();j++)
{
element.setAttribute(map.item(j).getLocalName(), map.item(j).getNodeValue());
}
Node node = xml1.adoptNode(element);
blog.appendChild(node);
}
DOMImplementationLS impl = (DOMImplementationLS) xml1.getImplementation();
System.out.println(impl.createLSSerializer().writeToString(destination ));
The problem is, this code will consider all the child nodes of "bpmn:process" tag as seperate node and will put directly under "bpmn:process"(all the sub chidren will also come under "bpmn:process"). the output looks like this
<bpmn:process id="Process_1" isExecutable="false">
//Here comes First xml nodes
//Second XML Content after merge
<bpmn:startEvent id="StartEvent_1">
</bpmn:startEvent>
**//This tag should be inside bpmn:startEvent tag**
<bpmn:outgoing>SequenceFlow_1i0zw0x</bpmn:outgoing>
<bpmn:intermediateThrowEvent id="IntermediateThrowEvent_00epl00">
</bpmn:intermediateThrowEvent>
**//THis should be inside above bpmn:intermediateThrowEvent tag**
<bpmn:incoming>SequenceFlow_1i0zw0x</bpmn:incoming>
</bpmn:process
But the Expected is
<bpmn:process id="Process_1" isExecutable="false">
//Here comes First xml Children
//Second XML Content
<bpmn:startEvent id="StartEvent_1">
// outgoing is Inside bpmn:startEvent tag
**<bpmn:outgoing>SequenceFlow_1i0zw0x</bpmn:outgoing>**
</bpmn:startEvent>
<bpmn:intermediateThrowEvent id="IntermediateThrowEvent_00epl00">
// Inside bpmn:intermediateThrowEvent tag
<bpmn:incoming>SequenceFlow_1i0zw0x</bpmn:incoming>
</bpmn:intermediateThrowEvent>
</bpmn:process
Please let me know the correct way of doing this.
Thanks,
XPath is a read-only language: you can't use it to construct new XML trees. For that you need XSLT or XQuery. Or DOM, if you really want to sink that low.
But this is so easy in XSLT that using DOM really seems a waste of effort. In XSLT you just need two template rules: the standard identity rule to copy everything unchanged, plus the rule
<xsl:template match="bpmn:process">
<xsl:copy-of select="."/>
<xsl:copy-of select="document('second.xml')//bpmn:process"/>
</xsl:template>

How to read xml using XPATH in Java

I want to read XML data using XPath in java, so for the information I have gathered I am not able to parse xml according to my requirement,
I just want to take the value of bankId
this the example of the xml
I want to read XML data using XPath in java, so for the information I have gathered I am not able to parse xml according to my requirement,
I just want to take the value of 'bankId'
this part of the example of the xml
<?xml version="1.0" encoding="UTF-8"?>
<p:RawData xsi:type="p:RawData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ba="http://service.bni.co.id/bancslink" xmlns:bo="http://service.bni.co.id/core/bo" xmlns:core="http://service.bni.co.id/core" xmlns:mhp="http://service.bni.co.id/mhp" xmlns:mpnG2="http://service.bni.co.id/mhp/mpn_g2" xmlns:mpnG2_1="http://service.bni.co.id/bancslink/mpn_g2" xmlns:p="http://BP_MultiHostPayment">
<boList>
<name>McpRequest</name>
<bo xsi:type="bo:CommonBillPaymentReq">
<billerCode>0128</billerCode>
<regionCode>0001</regionCode>
<billerName>MPN G2 IDR</billerName>
<billingNum>820150629548121</billingNum>
<customerName>EVA RAJAGUKGUK SH. M.KN </customerName>
<paymentMethod>2</paymentMethod>
<accountNum>0373163437</accountNum>
<trxAmount>50000</trxAmount>
<naration>820150629548121</naration>
<invoiceNum>820150629548121</invoiceNum>
<billInvoiceNum1>INVNUM1</billInvoiceNum1>
<billAmount1>0</billAmount1>
<billInvoiceNum2>INVNUM2</billInvoiceNum2>
<billAmount2>0</billAmount2>
<billInvoiceNum3>INVNUM3</billInvoiceNum3>
<billAmount3>0</billAmount3>
<isDecAmount>false</isDecAmount>
<trxDecAmount>50000</trxDecAmount>
</bo>
</boList>
<boList>
<name>McpTellerHeader</name>
<bo xsi:type="core:TellerHeader">
<tellerId>00004</tellerId>
<branchCode>0997</branchCode>
<overrideFlag>I</overrideFlag>
</bo>
</boList>
<boList>
<name>HostRequest</name>
<bo xsi:type="mhp:Request">
<header>
<hostId>MPN_G2</hostId>
<channelId>ATM</channelId>
<branchId></branchId>
<terminalId></terminalId>
<locationId></locationId>
<transDateTime>2015-06-30T22:26:33</transDateTime>
<transId>20150630T222633N042462J0000001969R840SLEXI0</transId>
</header>
<content xsi:type="mpnG2:PaymentReq">
<bankId>520009000990</bankId>
<billingInfo1>013</billingInfo1>
<billingInfo2>03</billingInfo2>
<billingInfo3>409257</billingInfo3>
<branchCode>0997</branchCode>
<channelType>7010</channelType>
<currency>IDR</currency>
<gmt>2015-06-30T15:26:33.942</gmt>
<localDatetime>2015-06-30T22:26:33.943</localDatetime>
<settlementDate>0701</settlementDate>
<switcherCode>001</switcherCode>
<terminalId>S1HKWGA032</terminalId>
<terminalLocation>0997</terminalLocation>
<transactionId>013978</transactionId>
<amount>50000</amount>
<billerAccountNumber>3010194605</billerAccountNumber>
<customerName>EVA RAJAGUKGUK SH. M.KN </customerName>
<ntb>000000058111</ntb>
<paymentCode>820150629548121</paymentCode>
</content>
</bo>
</boList>
</p:RawData>
this is my java code
try {
FileInputStream file = new FileInputStream(new File("C:/Log/contoh.xml"));
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
System.out.println("hup hup");
String expression = "/p:RawData/boList/boList/boList/bo/content[#xsi:type='mpnG2:PaymentReq']/bankId";
System.out.println(expression);
String bankId = xPath.compile(expression).evaluate(xmlDocument);
System.out.println(bankId);
System.out.println("hup hup 2");
expression = "/p:RawData/boList/boList/boList/bo/content[#xsi:type='mpnG2:PaymentReq']/bankId";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i=0; i < nodeList.getLength(); i++){
System.out.println(nodeList.item(i).getFirstChild().getNodeValue());
}
only this that appear when I run the code
hup hup
/p:RawData/boList/boList/boList/bo/content[#xsi:type='mpnG2:PaymentReq']/bankId
hup hup 2
any help will be pleasure :)
Try the following xpaths
//content[#xsi:type='mpnG2:PaymentReq']/bankId or
//content[#xsi:type='mpnG2:PaymentReq'][1]/bankId or
//bankId or
//bankId[1]
I've tested the xpaths for your xml in this online Xml Xpath tester
The XPath expression is wrong.
/p:RawData/boList/boList/boList/bo/content[#xsi:type='mpnG2:PaymentReq']/bankId
would select the element at:
<p:RawData>
<boList>
<boList>
<boList>
<bo>
<content xsi:type="mpnG2:PaymentReq" />
</bo>
</boList>
</boList>
</boList>
</RawData>
There is no such element in the XML.
You want
/p:RawData/boList[3]/bo/content[#xsi:type='mpnG2:PaymentReq']/bankId
To select the 3rd boList.

How to retrieve prefixed child elements using JDom

I have the following xml snippet from which I am trying to retrieve the first element using JDOM but I am getting nullpointer exception.please help me out if any one knows.
<db1:customer xmlns:db1="http://www.project1.com/db1">
<db1:customerId>22</db1:customerId>
<db1:customerName>PRASAD44</db1:customerName>
<db1:address>Chennai</db1:address>
<db1:email>pkk#gmail.com</db1:email>
<db1:lastUpdate>2014-08-01T00:00:00+05:30</db1:lastUpdate>
<db1:nameDetail>BSM_RESTeter</db1:nameDetail>
<db1:phoneBiz>9916347942</db1:phoneBiz>
<db1:phoneHome>9916347942</db1:phoneHome>
<db1:phoneMobile>944990031</db1:phoneMobile>
<db1:rating>22</db1:rating>
</db1:customer>
here is what I am doing,
SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("CommonFiles/file.xml");
Document doc = (Document) builder.build(xmlFile);
Element rootNode = doc.getRootElement();
Element customerid = rootNode.getChild("sure:customerId");
System.out.println("customerid ======"+customerid);
The print statement displays null.
When dealing with XML containing namespaces, you need to use the Namespace instance that's appropriate for your document. In this case, you have:
<db1:customer xmlns:db1="http://www.project1.com/db1">
The namespace here is http://www.project1.com/db1 and the prefix is db1.
In JDOM you can creaate a reference to a namespace with:
Namespace db1 = Namespace.getNamespace("db1", "http://www.project1.com/db1");
Now, when you retrieve the content in your document, use:
Element customerid = rootNode.getChild("customerId", db1);
Note that you get content using the Namespace object, not the prefix for the element (there is no "db1:" prefix for the "customerId"

How do I get the tag 'Name' from a XML Node in Java (Android)

I have a tiny little problem parsing an XML file in Java (Android).
I have an XML file that is like this:
<Events>
<Event Name="Olympus Has Fallen">
...
</Event>
<Event Name="Iron Man 3">
...
</Event>
</Events>
I already managed to get the NodeList by doing this:
URL url = new URL("********");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("Event");
Also I managed to get every single item of the NodeList by doing this:
for (int i = 0; i < nodeList.getLength(); i++) {
// Item
Node node = nodeList.item(i);
Log.i("film", node.getNodeName());
}
But this just Logs: "Event" instead of the value of the Name tag.
How do I output the value of this 'name' tag from the XML.
Can anyone help me with this one?
Thanks in advance!
But this just Logs: "Event" instead of the value of the Name tag.
Yes, because you're asking for the name of the element. There isn't a Name "tag" - there's a Name attribute, and that's what you should find:
// Only check in elements, and only those which actually have attributes.
if (node.hasAttributes()) {
NamedNodeMap attributes = node.getAttributes();
Node nameAttribute = attributes.getNamedItem("Name");
if (nameAttribute != null) {
System.out.println("Name attribute: " + nameAttribute.getTextContent());
}
}
(It's very important to be precise in terminology - it's worth knowing the difference between nodes, elements, attributes etc. It will help you enormously both when communicating with others and when looking for the right bits of API to call.)

Categories