【问题标题】:Remove XML Node using java parser使用 java 解析器删除 XML 节点
【发布时间】:2010-09-15 11:39:41
【问题描述】:

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

请指教。

【问题讨论】:

  • @user274069:XPath 是一种用于选择 XML 树节点的托管语言。它不会改变树。如果您需要 XSLT 解决方案,请重新标记。

标签: java xml


【解决方案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 和样式表来删除节点:

【讨论】:

  • 很好用。非常感谢。如何获取字符串中的文本??
  • 有趣。如果您希望通过属性及其值查找 XML 标记,如何使用相同的技术?例如:
  • 谢谢。 xml 属性顺序已更改。有什么办法可以防止改变其他人的属性顺序?
【解决方案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);
    }
}

【讨论】:

【解决方案3】:

这里是使用带有谓词的 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");
    }

}

【讨论】:

    【解决方案4】:

    我用 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']");

    【讨论】:

      猜你喜欢
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-17
      相关资源
      最近更新 更多