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>
Related
Does anybody know, how to find self closing tags of the XML document?
I am able to get all the elements of specific type, but I am unable to find elements, that are self closing and also, I need to find elements, with no attributes.
var dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
var db = dbf.newDocumentBuilder();
var urlToFile = MyClass.class.getClassLoader().getResource("file.xml");
var file = Paths.get(urlToFile .toURI()).toFile();
var doc = db.parse(file);
doc.getDocumentElement().normalize();
var list = doc.getElementsByTagName("myTag");
for (int i = 0; i < list.getLength(); i++) {
var node = list.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
var bits = node.getChildNodes();
for (int j = 0; j < bits.getLength(); j++) {
if (bits.item(j).hasAttributes()) {
// var parrentAttrName = bits.item(j).getNodeName();
// getValueFromAttribute is my private method
var nameAttrValue = getValueFromAttribute(bits, j, "name");
var stateAttrValue = getValueFromAttribute(bits, j, "state");
bits.addElementToList(new MyBit(nameAttrValue, stateAttrValue));
}
if(!bit.item(j).hasAttributes()) {
// not working
System.out.println(bits.item(j));
}
}
}
}
My XML file has two types of myTag tags:
Pair tags, that contains another nested child elements <myTag><someElementHere /></myTag>
Self-closing tags, that are specifying some other behaviour <myTag/>
Is there a mechanism, to find this kind elements? The one possible thing would be, to match the regex of self closing tags, but I was thinking of some other solution possible.
Once the document is parsed, and the content loaded into a DOM, there are no tags, there are only nodes. You can tell that an element node is empty (by asking whether it has any child nodes), but you can't tell whether the empty element was originally written as <myTag/> or as <myTag></myTag>. That's the author's choice and it should make no difference to the recipient.
Your question indicates that you are very confused about the difference between the lexical XML (the tags and angle brackets), and the tree model of the XML represented by the DOM.
Self closing tags have no children but so do empty tags.
That said, XPath could be used to find elements with no children or with attributes
Given
<?xml version="1.0" encoding="UTF-8"?>
<root>
<test/>
<test a="a"/>
<empty></empty>
<test>
<a>a</a>
</test>
<test>text</test>
<deep>
<some b="b" />
</deep>
</root>
Find elements with no children with //*[count(./descendant::*) = 0 and count(./text()) = 0]
xmllint --shell test.xml
</ cat //*[count(./descendant::*) = 0 and count(./text()) = 0]
<test/>
-------
<test a="a"/>
-------
<empty/>
-------
<some b="b"/>
Find elements with attributes with xpath //*[count(./#*)> 0]
/ > cat //*[count(./#*)> 0]
-------
<test a="a"/>
-------
<some b="b"/>
Note: XPath is language agnostic so it should work in 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 !
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.
<root>
<h id="1">
<d value="1,2,3,4,5"><open>10:00</open><close>23:00</close></d>
<d value="6"><open>10:00</open><close>2:00</close></d>
<d value="7"><open>10:00</open><close>21:00</close></d>
</h>
<h id="2">
</h>
</root>
Here I have the XML which root has list of <h> tagged nodes. Now I need to break these into parts and set it into different variables (add into a map).
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(new ByteArrayInputStream(data.getBytes("utf-8"))));
NodeList nList = doc.getElementsByTagName("h");
for (int i = 0; i < nList.getLength(); i++)
{
Node nNode = nList.item(i);
System.out.println(nNode.getAttributes().getNamedItem("id") + " " + ?????);
}
what should I call in order to get the value (String value) of a nNode ?
Here is what Im looking for as the asnwer for the above code once some one fills the ????
1 <h id="1"><d value="1,2,3,4,5"><open>10:00</open><close>23:00</close></d><d value="6">open>10:00</open><close>2:00</close></d><d value="7"><open>10:00</open><close>21:00</close></d></h>
2 <h id="2"></h>
And i don't mind having as root element
You can use Node.getTextContent() to conveniently get all the text of a node (gets text of children as well).
See Parsing xml file contents without knowing xml file structure for a short example.
If you're trying to get the value attributes of the d nodes (I can't actually tell, your question is slightly unclear to me), then it would be different -- for that you would iterate through the children of each h node (use getChildNodes() or getFirstChild() + getNextSibling()) then grab their value attributes just as you are getting the id attribute of the h nodes (the above link also shows an example of iterating through child nodes).
Have you tried jDom library? http://www.jdom.org/docs/apidocs/org/jdom2/output/XMLOutputter.html
XMLOutputter outp = new XMLOutputter();
String s = outp.outputString(your_jdom_element);
Have you tried nNode.toString() if you are using Node from javax.xml.soap.Node.
You can use that:
http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Node.html#getTextContent()
but your sample nNode has other nodes, not just text. It seems you need helper method to construct String from child nodes.
Pass your nNode to nodeToString
XML Node to String in Java
I would like to insert a node in an xml file using Java DOM. I am actually editing a lot of contents of a dummy file in order to mofidy it like the original.
I would want to add an open node and close node in between the following file;
<?xml version="1.0" encoding="utf-8"?>
<Memory xmlns:xyz="http://www.w3.org/2001/XMLSchema-instance"
xmlns:abc="http://www.w3.org/2001/XMLSchema" Derivative="ABC"
xmlns="http://..">
///////////<Address> ///////////(which I would like to insert)
<Block ---------
--------
-------
/>
////////// </Address> /////////(which I would like to insert)
<Parameters Thread ="yyyy" />
</Memory>
I hereby request you to let me know how to I insert -- in between the xml file?
Thanks in advance.!
What I have tried doing is;
Element child = doc.createElement("Address");
child.appendChild(doc.createTextNode("Block"));
root.appendChild(child);
But this gives me an output like;
<Address> Block </Address> and not the way i expect :(
And now, what I have tried is to add these lines;
Element cd = doc.createElement("Address");
Node Block = root.getFirstChild().getNextSibling();
cd.appendChild(Block);
root.insertBefore(cd, root.getFirstChild());
But still, this is not the output which i am looking for. I got this output as
---------
What you want is probably:
Node parent = block.getParentNode()
Node blockRemoved = parent.removeChild(block);
// Create address
parent.appendChild(address);
address.appendChild(blockRemoved);
This is the standard way to re-attach a node in another place under W3C DOM.
Here:
DocumentBuilder b = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = b.parse(...);
// Parent of existing Block elements and new Address elemet
// Might be retrieved differently depending on
// actual structure
Element parent = document.getDocumentElement();
Element address = document.createElement("address");
NodeList nl = parent.getElementsByTagName("Block");
for (int i = 0; i < nl.getLength(); ++i) {
Element block = (Element) nl.item(i);
if (i == 0)
parent.insertBefore(address, block);
parent.removeChild(block);
address.appendChild(block);
}
// UPDATE: how to pretty print
LSSerializer serializer =
((DOMImplementationLS)document.getImplementation()).createLSSerializer();
serializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
LSOutput output =
((DOMImplementationLS)document.getImplementation()).createLSOutput();
output.setByteStream(System.out);
serializer.write(document, output);
I assume you are using the W3C DOM (e.g. http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html ). If so try
insertBefore(address, block);