无法通过 Java 代码从 XML 文档中删除元素和子元素

Can't remove element and child element from an XML document by Java code

这是我的 xml 文档:

<definitions>       
<task name="TASK1"
     class="CLASS"
     group="GROUP">
  <trigger count="3" interval="400"/>
  <property xmlns:task="URI"
            name="PROPERTY2"
            value="VALUE1"/>
  <property xmlns:task="URI"
            name="PROPERTY2"
            value="VALUE2"/>
</task>
<task name="TASK1"
     class="CLASS"
     group="GROUP">
  <trigger count="1" interval="600"/>
  <property xmlns:task="URI"
            name="PROPERTY2"
            value="VALUE1"/>
  <property xmlns:task="URI"
            name="PROPERTY2"
            value="VALUE2"/>
</task>
<another_tag name="a_name"/>
<another_tag2 name="a_name2"/>
<another_tag3>  something in the middle </another_tag3>

</definitions>

我必须删除所有 <task> 标签及其中的内容。我使用了这个 java 代码:

Document esb = new Document();

    SAXBuilder saxBuilder = new SAXBuilder();


    try {
       esb = saxBuilder.build(new File("C:\...path\file.xml")); 
    }
    catch (JDOMException ex) {
       System.err.println(ex);
    }
    catch (IOException ex) {
       System.err.println(ex);
    }
    Element root = esb.getRootElement();
    boolean b = root.removeChild("task");
    System.out.println(b);

我无法理解如何获取不带 <task> 标签且仅包含 <another_tag> 标签的 xml 文件。我一直在寻找其他解决方案,但没有任何用处。我也使用了 removeContent() 方法,但没有。我导入了 jdom2 库,我需要使用最近的库,因为 jdom 和 jdom2 之间的交互不好,所以我宁愿只使用最近的库。关于如何从此 xml CODE 中删除某些元素的任何建议?

api 函数 'removeChild' 是这样说的: ...这将删除具有给定本地名称且不属于任何名称空间的第一个 child 元素(深度一层)...

removeChild 函数只删除一个 child。因此,如果您想删除所有具有特定名称的 child,您需要使用循环。如果函数调用找不到具有所需名称的节点,它 returns 为 false.

如果我使用您的示例 xml 第三次调用 removeChild returns 为 false。所以下面的代码会删除所有任务 childs

...
    boolean b = root.removeChild("task");
    while (b)
        b = root.removeChild("task");
...

除了 OkieOth 所说的,您只是删除了第一个任务。

另一个问题是您没有将 JDOM 再次写入文件。您需要保存现有文件才能看到更改。

如果您想将更改应用回文件,请考虑:

SAXBuilder saxBuilder = new SAXBuilder();

try {
    Document esb = saxBuilder.build(new File("C:\...path\file.xml")); 
    Element root = esb.getRootElement();
    boolean b = root.removeChild("task");
    System.out.println(b);
    XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
    try (OutputStream os = new FileOutputStream("C:\...path\file.xml")) {
        xout.output(os, esb)
    }
}
catch (JDOMException ex) {
   System.err.println(ex);
}
catch (IOException ex) {
   System.err.println(ex);
}

我通过管理命名空间解决了这个问题。有代码:`

Document doc = new Document();

SAXBuilder saxBuilder = new SAXBuilder();
try {
       doc = saxBuilder.build(new File("....path\MyXMLfile.xml")); 
    }
    catch (JDOMException ex) {
       System.err.println(ex);
    }
    catch (IOException ex) {
       System.err.println(ex);
    }


    Element root = esb.getRootElement();
    System.out.println(root.getName());  // it prints "definitions"

    Namespace namespace = Namespace.getNamespace("task","http://....myDefinitionsNamespace....");

    boolean b = root.removeChildren("task", namespace);

    System.out.println(b);

    XMLOutputter xmlOutputter = new XMLOutputter();
    xmlOutputter.setFormat(Format.getPrettyFormat());
    System.out.println(xmlOutputter.outputString(doc)); //so we can see new XML FILE

为了理解这段代码,我们也需要开始xml:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://....myDefinitionsNamespace....">
<task name="MyTask"
     class="....myClass...."
     group="....myGroup...."> 
<taskChild/>
</task>
<anotherTag1/>
<anotherTag2>
<task/>
.
.
.
</definitions>

结果是一个没有每个任务标签的 XML 文件,它将只包含 anotherTags。然后您需要定义输出(例如输出到带有 FileOutputStream 实例的文件中)。 感谢@OkieOth 和@rolfl。

这是要使用的代码XPath to remove all task nodes incrementally using vtd-xml

import com.ximpleware.*;
import java.io.*;

public class removeElement {
    public static void main(String s[]) throws VTDException,IOException{
        VTDGen vg = new VTDGen();
        if (!vg.parseFile("input.xml", false))
            return;
        VTDNav vn = vg.getNav();
        AutoPilot ap = new AutoPilot(vn);
        ap.selectXPath("/definition/task");
        XMLModifier xm = new XMLModifier(vn);
        int i=0;
        while((i=ap.evalXPath())!=-1){
            xm.remove();
        }
        xm.output("output.xml");

    }
}