Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java DOM - Inserting an element, after another

Tags:

java

dom

xml

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();
        }
    }
}
like image 904
Andrei Ciobanu Avatar asked Aug 04 '10 11:08

Andrei Ciobanu


People also ask

How do you add an element after another element?

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.

Is there insertAfter in JavaScript?

Note: There is no insertAfter() method. It can be emulated by combining the insertBefore method with Node. nextSibling .

Which method is triggered when an element is added to the DOM?

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.


2 Answers

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.

like image 161
f1sh Avatar answered Sep 19 '22 20:09

f1sh


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.

like image 32
Lukas Eder Avatar answered Sep 19 '22 20:09

Lukas Eder