Given the following XML file:
<?xml version="1.0" encoding="UTF-8"?>
<process
name="TestSVG2"
xmlns="http://www.example.org"
targetNamespace="http://www.example.org"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<sequence>
<receive name="Receive1" createInstance="yes"/>
<assign name="Assign1"/>
<invoke name="Invoke1"/>
<assign name="Assign2"/>
<reply name="Reply1"/>
</sequence>
</process>
I want to add a new element inside the <sequence></sequence>
after a certain pre-existing element. For example if I want to add the node after "Assign1"
, the new XML should like this:
<sequence>
<receive name="Receive1" createInstance="yes"/>
<assign name="Assign1"/>
<newtype name="NewNode"/>
<invoke name="Invoke1"/>
<assign name="Assign2"/>
<reply name="Reply1"/>
</sequence>
I have to do this by using Java DOM, in a function. The function signature should like this:
public void addActionDom(String name, String stepType, String stepName)
Where:
name
is the pre-existing element, after which the insertion will be made;stepType
is the inserted element type;stepName
is the name attribute of the newly inserted element.Currently I am lacking experience with JDOM, or any other Java XML library. Can you please give a sample code, or point me to a tutorial where an insertion after a certain element is made.
This is the code I have until now:
public void addActionDom(String name, String stepType, String stepName) {
File xmlFile = new File(path + "/resources/" + BPELFilename);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
try {
/* Load XML */
db = dbf.newDocumentBuilder();
Document doc = db.parse(xmlFile);
doc.getDocumentElement().normalize();
/* Iterate throughout the type tags and delete */
for (String cTag : typeTags) {
NodeList cnl = doc.getElementsByTagName(cTag);
for (int i = 0; i < cnl.getLength(); ++i) {
Node cnode = cnl.item(i);
if (cnode.getNodeType() == Node.ELEMENT_NODE) {
Element elem = (Element)cnode; // 'elem' Element after which the insertion should be made
if (elem.getAttribute("name").equals(name)) {
Element newElement = doc.createElement(stepType); // Element to be inserted
newElement.setAttribute("name", stepName);
// CODE HERE
}
}
}
}
/* Save the editing */
Transformer transformer =
TransformerFactory.newInstance().newTransformer();
StreamResult result =
new StreamResult(new FileOutputStream(path + "/resources/" +
BPELFilename));
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
} catch (Exception e) {
/* ParserConfigurationException */
/* SAXException */
/* IOException */
/* TransformerConfigurationException */
/* TransformerException */
/* Exception */
e.printStackTrace();
}
}
}
To insert an element after an existing element in the DOM tree, you follow these steps: First, select the parent node of the existing element. Then, insert the new element before (insertBefore()) the next sibling (nextSibling) of the existing element.
Note: There is no insertAfter() method. It can be emulated by combining the insertBefore method with Node. nextSibling .
CSS animations Basically, the idea is to create an animation which would be triggered once an element has been added to the DOM. The moment the animation starts, the animationstart event will be fired: if you have attached an event handler to that event, you'd know exactly when the element has been added to the DOM.
Ok, Aaron Digulla beat me regarding speed. Had to figure it out myself as well.
I didnt use cnl.item(i+1)
but nextSibling()
:
Element newElement = doc.createElement(stepType); // Element to be inserted
newElement.setAttribute("name", stepName);
elem.getParentNode().insertBefore(newElement, elem.getNextSibling());
You cannot insert Nodes at a specified index. The only node-inserting methods are
appendChild(Node node) //appends the given child to the end of the list of children
and
insertBefore(Node new, Node child) //inserts "new" into the list, before the 'child' node.
If there was a insertAfter(Node new, Node child) method, this would be very easy for you. But there isn't, unfortunately.
As others have pointed out, the DOM API is quite verbose for such simple operations. If you use something like jOOX to wrap the DOM API, you could write any of the following:
// Find the element using XPath, and insert XML text after it
$(document).xpath("//sequence/assign[@name='Assign1']")
.after("<newtype name=\"NewNode\"/>");
// Find the element using jOOX API, and insert an object after it
$(document).find("sequence")
.find("assign")
.filter(attr("name", "Assign1"))
.after($("newtype").attr("name", "NewNode"));
Note how the API resembles that of jQuery.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With