使用 Java 解析器删除 XML 节点

2022-09-03 14:41:24

在下面的示例 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>

请指教。


答案 1

替代 DOM 方法

或者,您可以使用 JDK 中的 XPath 功能查找值为“13”的“B”元素,然后将其从其父级中删除,而不是对 XML 文档进行暴力遍历:

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

}

使用 XPath 的优点是更易于维护,如果结构发生更改,只需对代码进行一行更改即可。此外,如果文档的深度增加,则基于 XPath 的解决方案将保持相同的行数。

非 DOM 方法

如果您不想将 XML 具体化为 DOM。您可以使用 Transformer 和样式表来删除节点:


答案 2

如果您使用的是 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);
    }
}

推荐