Java DOM - вставка элемента после другого - PullRequest
10 голосов
/ 04 августа 2010

С учетом следующего XML-файла:

<?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>

Я хочу добавить новый элемент внутри <sequence></sequence> после определенного ранее существующего элемента . Например, если я хочу добавить узел после "Assign1", новый XML должен выглядеть следующим образом:

   <sequence>
      <receive name="Receive1" createInstance="yes"/>
      <assign name="Assign1"/>
      <newtype name="NewNode"/>
      <invoke name="Invoke1"/>
      <assign name="Assign2"/>
      <reply name="Reply1"/>
   </sequence>

Я должен сделать это, используя Java DOM в функции. Подпись функции должна выглядеть так:

 public void addActionDom(String name, String stepType, String stepName)

Где:

  • name - это уже существующий элемент, после которого будет произведена вставка;
  • stepType - тип вставленного элемента;
  • stepName - это атрибут имени вновь вставленного элемента.

В настоящее время мне не хватает опыта работы с JDOM или какой-либо другой библиотекой Java XML. Можете ли вы дать пример кода или указать мне учебник, где вставка после определенного элемента.

Это код, который у меня есть до сих пор:

    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();
        }
    }
}

Ответы [ 4 ]

17 голосов
/ 04 августа 2010

Хорошо, Аарон Дигулла победил меня в отношении скорости. Пришлось разобраться и самому. Я не использовал cnl.item(i+1), но nextSibling():

Element newElement = doc.createElement(stepType); // Element to be inserted 
newElement.setAttribute("name", stepName);
elem.getParentNode().insertBefore(newElement, elem.getNextSibling());

Нельзя вставлять узлы по указанному индексу. Единственные методы вставки узла -

appendChild(Node node) //appends the given child to the end of the list of children

и

insertBefore(Node new, Node child) //inserts "new" into the list, before the 'child' node.

Если бы существовал метод insertAfter (Node new, Node child), это было бы очень легко для вас. Но нет, к сожалению.

4 голосов
/ 04 августа 2010

Это просто, но API org.w3c.dom немного ... странно для этого:

Node next = cnl.item(i + 1);
Node newChild = createChild();
next.getParent().insertBefore(newChild, next);

С JDom все проще:

Node newChild = createChild();
cnl.getParent().addContent(i, newChild);
2 голосов
/ 12 июля 2012

Как уже отмечали другие, DOM API довольно многословен для таких простых операций. Если вы используете что-то вроде jOOX , чтобы обернуть DOM API, вы можете написать следующее:

// 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"));

Обратите внимание, что API похож на jQuery .

2 голосов
/ 04 августа 2010

Это не проверено, но вы должны уметь:

elem.getParentNode().insertBefore(newElement, elem.getNextSibling());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...