的Java查找并删除子节点
问题描述:
我有如下的XML文件:的Java查找并删除子节点
<CourseList>
<Course>
<CourseName>CoreJava</CourseName>
<Teacher>Bui Duy Linh</Teacher>
<Duration>90 minutes</Duration>
<Student>
<StudentID>C001</StudentID>
<StudentName>Nam</StudentName>
<DateRegister>15/11/2016</DateRegister>
</Student>
<Student>
<StudentID>C002</StudentID>
<StudentName>Vi</StudentName>
<DateRegister>13/11/2016</DateRegister>
</Student>
</Course>
而且我想删除ID为C001的学生,但我的搜索功能似乎返回null
public static Node searchByID(String id, Document doc) {
try {
XPathFactory xpf = XPathFactory.newInstance();
XPath xp = xpf.newXPath();
NodeList list = (NodeList) xp.evaluate("CourseList/Course/Student/StudentID", doc, XPathConstants.NODESET);
for (int i = 0; i < list.getLength(); i++) {
String content = list.item(i).getTextContent();
if (content.equalsIgnoreCase(id)) {
Node p = list.item(i).getParentNode();
return p;
}
}
} catch (XPathExpressionException ex) {
Logger.getLogger(AssignmentXML.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
有没有办法解决它?我应该使用DOM吗?感谢任何人的帮助
答
你说它返回null,但它不。它返回Node
具有给定ID的<Student>
节点的对象。如果您打印的节点上,您可以:
[Student: null]
也就是说不空值,而是一个Node
对象,具有toString()
方法是这样的:
public String toString() {
return "["+getNodeName()+": "+getNodeValue()+"]";
}
而且根据Node
javadoc对于Element
节点:
-
nodeName
是“一样Element.tagName” -
nodeValue
是“空”
如果你真的改变了这个节点中使用的文字:
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(node), new StreamResult(System.out));
您将获得:
<Student>
<StudentID>C001</StudentID>
<StudentName>Nam</StudentName>
<DateRegister>15/11/2016</DateRegister>
</Student>
答
那么,结果没有错的搜索,但与删除功能。 我的旧代码:
Node delNode = searchByID(id, doc);
doc.getDocumentElement().removeChild(delNode);
只删除文档,节点不是元素中的节点。我这样做是为了解决:
Node delNode = searchByID(id, doc);
delNode.getParentNode().removeChild(delNode);
感谢你们反正帮助:)
答
对于OP和未来的读者,需要考虑到重组或重新设计的XML文档时使用XSLT。没有循环或如果/然后逻辑是必要的。 XSLT是一种原生的专用语言,专为此确切需要而设计。与通用语言(包括C#,Python,Perl,PHP和VB)一样,Java也维护XSLT 1.0处理器。下面是OP的请求的一个工作示例。
XSLT脚本(保存为.xsl或。XSLT在Java中使用)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<!-- Identity Transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Removes all Student nodes with C001 ID condition -->
<xsl:template match="Student[StudentID='C001']"/>
</xsl:transform>
的Java脚本
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.OutputKeys;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class CourseList {
public static void main(String[] args) throws IOException, URISyntaxException,
SAXException,
ParserConfigurationException,
TransformerException {
// LOAD XML AND XSL DOCUMENTS
String inputXML = "C:\\Path\\To\\Input.xml";
String xslFile = "C:\\Path\\To\\XSLTScript.xsl";
String outputXML = "C:\\Path\\To\\Output.xml";
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse (new File(inputXML));
Source xslt = new StreamSource(new File(xslFile));
// XSLT TRANSFORMATION WITH PRETTY PRINT
TransformerFactory prettyPrint = TransformerFactory.newInstance();
Transformer transformer = prettyPrint.newTransformer(xslt);
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(outputXML));
transformer.transform(source, result);
}
}
输出
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<CourseList>
<Course>
<CourseName>CoreJava</CourseName>
<Teacher>Bui Duy Linh</Teacher>
<Duration>90 minutes</Duration>
<Student>
<StudentID>C002</StudentID>
<StudentName>Vi</StudentName>
<DateRegister>13/11/2016</DateRegister>
</Student>
</Course>
</CourseList>
你调试代码? –
是的,内容确实返回C001,并且我设置了id = C001,但由于某种原因它仍然返回null – user3676506
我试图运行您的代码。正确的结果(学生节点)已返回。我只在XML的末尾添加了“”。 – saka1029