我习惯使用C ++库进行xml解析,即rapidxml和tinyxml。构建在DOM解析器中的java对我来说绝对没有意义。经过一番努力,我能够存储我需要的根节点,但现在我想找到一个具有特定id的标签。
以下是xml示例:
<?xml version="1.0" encoding="UTF-8"?>
<adventure title="Test Adventure" author="Tester">
<enemies>
<enemy id="e1" difficulty="1">Enemy1</enemy>
</enemies>
<story>
<narration id="n1" action="d1">It's adventure time!</narration>
<decision id="d1">
<description>Would you like to participate?</description>
<choice action="n2">Yes, please.</choice>
<choice action="n3">Not the slightest.</choice>
</decision>
<narration id="n2" action="end">Great choice!</narration>
<narration id="n3" action="end">Okay...</narration>
</story>
</adventure>
我将<story>
节点存储在Node
实例中。从那里,我想找到具有特定id的节点(假设'n3'节点)。
我想使用这种方法:
private Node findNode(String id) {
Node node = storyNode.getFirstChild();
while ( node != null ) {
Element elem = (Element)node;
if ( elem.getAttribute("id") == id ) {
return node;
}
node = node.getNextSibling();
}
return null;
}
这是我使用C ++库的方法,但这离工作还很远......我不明白为什么我要为这么简单的任务进行类型转换。为什么Node
不能通过指定属性名来获取属性的方法。 getFirstChild()
似乎甚至没有回到第一个孩子......
我在网上找到的包装类要么是30循环深,要么更难使用。为什么这么复杂?我做错了什么?
答案 0 :(得分:3)
为什么API如此...真棒......将归结为它的设计原因和方式。解决方案可能比您想象的更简单。
您可以使用的功能之一是XPath实现,它被吹捧为XML的查询语言。
因此,您可以简单地使用//*[@id='n1']
之类的内容来查找id
属性等于n1
的任何节点,而不是尝试遍历每个节点和每个子节点。例子)。
使用您的示例XML和以下代码...
try {
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("Test.xml"));
Node root = doc.getDocumentElement();
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression xExpress = xPath.compile("//*[@id='n1']");
NodeList nl = (NodeList)xExpress.evaluate(root, XPathConstants.NODESET);
System.out.println("Found " + nl.getLength() + " matches");
} catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException ex) {
ex.printStackTrace();
}
此输出
Found 1 matches
请查看XPath了解更多详情