给出以下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
是新插入元素的name属性。目前我缺乏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();
}
}
}
答案 0 :(得分:17)
好的,Aaron Digulla在速度上打败了我。不得不自己搞清楚。
我没有使用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)方法,这对您来说非常容易。但不幸的是,没有。
答案 1 :(得分:4)
这很简单但是org.w3c.dom API有点奇怪:
Node next = cnl.item(i + 1);
Node newChild = createChild();
next.getParent().insertBefore(newChild, next);
使用JDom,它更简单:
Node newChild = createChild();
cnl.getParent().addContent(i, newChild);
答案 2 :(得分:2)
这未经过测试,但您应该可以:
elem.getParentNode().insertBefore(newElement, elem.getNextSibling());
答案 3 :(得分:2)
正如其他人所指出的,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的类似。