使用java解析器删除XML节点

时间:2010-09-15 11:39:42

标签: java xml

在下面的示例XML中,如何使用java解析器删除整个B节点,如果E = 13。

<xml>
   <A>
     <B>
       <C>
         <E>11</E>
         <F>12</F>
       </C>
    </B>
    <B>
       <C>
         <E>13</E>
         <F>14</F>
      </C>
    </B>
  </A>

请告知。

4 个答案:

答案 0 :(得分:14)

替代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和样式表来删除节点:

答案 1 :(得分: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);
    }
}

答案 2 :(得分:0)

我用Blaise代码尝试了这个文件示例,我得到了

Exception in thread "main" java.lang.NullPointerException
    at myxml.xmlParty2.main(xmlParty2.java:22)

这是文件

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

,Xptah查询为XPathExpression expression = xpath.compile("/favoris/workflow[@id='wf2333']");

答案 3 :(得分:0)

以下是使用带谓词的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");
    }

}