Учитывая следующий 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();
}
}
}
Хорошо, Аарон Дигулла победил меня по скорости. Пришлось разобраться и самому.
Я не использовал 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 (новый узел, дочерний узел), это было бы очень легко для вас. Но, к сожалению, нет.
Это просто, но 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);
Это не проверено, но вы должны уметь:
elem.getParentNode().insertBefore(newElement, elem.getNextSibling());