使用 java 解析器删除 XML 节点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3717215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove XML Node using java parser
提问by user274069
In the below sample XML, how to remove Entire B Node if E=13 using java parser.
在下面的示例 XML 中,如果 E=13,如何使用 java 解析器删除整个 B 节点。
<xml>
<A>
<B>
<C>
<E>11</E>
<F>12</F>
</C>
</B>
<B>
<C>
<E>13</E>
<F>14</F>
</C>
</B>
</A>
Please advise.
请指教。
采纳答案by bdoughan
Alternative DOM Approach
替代 DOM 方法
Alternatively, instead of doing a brute force traversal of the XML document you could use the XPath capabilities in the JDK to find the "B" element with value "13" and then remove it from its parent:
或者,您可以使用 JDK 中的 XPath 功能查找值为“13”的“B”元素,然后将其从其父元素中删除:
import java.io.File;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import org.w3c.dom.*;
public class Demo {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document document = dbf.newDocumentBuilder().parse(new File("input.xml"));
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
XPathExpression expression = xpath.compile("//A/B[C/E/text()=13]");
Node b13Node = (Node) expression.evaluate(document, XPathConstants.NODE);
b13Node.getParentNode().removeChild(b13Node);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.transform(new DOMSource(document), new StreamResult(System.out));
}
}
The advantage of using an XPath it's easier to maintain, if the structure changes it's just a one line change to your code. Also if the depth of your document grows the XPath based solution stays the same number of lines.
使用 XPath 的优点是更容易维护,如果结构发生变化,只需对代码进行一行更改。此外,如果您的文档深度增加,基于 XPath 的解决方案将保持相同的行数。
Non-DOM Approach
非 DOM 方法
If you don't want to materialize your XML as a DOM. You could use a Transformer and a stylesheet to remove a node:
如果您不想将 XML 实现为 DOM。您可以使用 Transformer 和样式表来删除节点:
回答by dogbane
It's easy if you are using DOM. Just traverse the document and keep track of the B nodes. When you hit an E=13 node, remove the B node. Here is some code to help:
如果您使用 DOM,这很容易。只需遍历文档并跟踪 B 节点。当您遇到 E=13 节点时,删除 B 节点。这里有一些代码可以提供帮助:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().parse(new File("file.xml"));
DocumentTraversal traversal = (DocumentTraversal) doc;
Node a = doc.getDocumentElement();
NodeIterator iterator = traversal.createNodeIterator(a, NodeFilter.SHOW_ELEMENT, null, true);
Element b = null;
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
Element e = (Element) n;
if ("B".equals(e.getTagName())) {
b = e;
} else if ("E".equals(e.getTagName()) && "13".equals(e.getTextContent()) && b != null) {
a.removeChild(b);
}
}
回答by Ali Ben Messaoud
I tried this example of file with the Blaise code and I get
我用 Blaise 代码尝试了这个文件示例,我得到了
Exception in thread "main" java.lang.NullPointerException
at myxml.xmlParty2.main(xmlParty2.java:22)
This is the file
这是文件
<?xml version="1.0" encoding="UTF-8"?>
<favoris>
<workflow codewf="wf2333">
<information>
<title>wf2333</title>
<desc>desc_title_5</desc>
<nberState>2</nberState>
<text>Impossible de joindre Cliquez sur le lien ci-dessous pour effectuer une nouvelle tentative.</text>
</information>
<states>
<state id="1" IDemployee="2">desc_wf_1_etat_1</state>
<state id="2" IDemployee="3">desc_wf_1_etat_2</state>
</states>
</workflow>
<workflow codewf="wf2334">
<information>
<title>wf2334</title>
<desc>desc_title_5</desc>
<nberState>2</nberState>
<text>Impossible de joindre Cliquez sur le lien ci-dessous pour effectuer une nouvelle tentative.</text>
</information>
<states>
<state id="1" IDemployee="2">desc_wf_1_etat_1</state>
<state id="2" IDemployee="3">desc_wf_1_etat_2</state>
</states>
</workflow>
</favoris>
and the Xptah Query is XPathExpression expression = xpath.compile("/favoris/workflow[@id='wf2333']");
Xptah 查询是 XPathExpression expression = xpath.compile("/favoris/workflow[@id='wf2333']");
回答by vtd-xml-author
Here is the code of removing node B using XPath with predicate. It is based on VTD-XML, which uniquely implements incremental update.
这是使用带谓词的 XPath 删除节点 B 的代码。它基于VTD-XML,独特地实现了增量更新。
import com.ximpleware.*;
import java.io.*;
public class removeNode {
public static void main(String s[]) throws VTDException, IOException{
VTDGen vg = new VTDGen();
if (!vg.parseFile("input.xml", false));
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot(vn);
XMLModifier xm = new XMLModifier(vn);
ap.selectXPath("/xml/A/B[C/E='13']");
while (ap.evalXPath()!=-1){
xm.remove();
}
xm.output("output.xml");
}
}