Не удается удалить элемент и дочерний элемент из документа XML с помощью кода Java
Это мой документ 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);
Я не могу понять, как получить XML-файл без <task>
тег и содержащий только <another_tag>
тег. Я искал другие решения, но ничего полезного. Я также использовал метод removeContent(), но ничего. Я импортировал библиотеки jdom2, мне нужно использовать последние библиотеки, потому что между jdom и jdom2 существует плохое взаимодействие, поэтому я бы предпочел использовать только последние библиотеки. Любое предложение о том, как удалить какой-либо элемент из этого XML-кода?
4 ответа
Я решил эту проблему, управляя пространством имен. Есть код:`
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-файл без каждого тега задачи, он будет содержать только другие теги. Затем вам нужно определить вывод (например, в файл с экземпляром FileOutputStream). Спасибо @OkieOth и @rolfl.
API говорит это для функции 'removeChild': ... Это удаляет первый дочерний элемент (на один уровень глубины) с заданным локальным именем и принадлежащий без пространства имен...
Функция removeChild удаляет только одного дочернего элемента. Поэтому, если вы хотите удалить всех потомков с определенным именем, вам нужно использовать цикл. Если вызов функции не может найти узел с нужным именем, он возвращает значение false.
Если я работаю с вашим примером xml, третий вызов removeChild вернётся с false. Поэтому следующий код удалит все дочерние элементы задачи
...
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);
}
Вот код для использования XPath для постепенного удаления всех узлов задач с использованием 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");
}
}