如何查找具有特定属性值的子元素

时间:2013-12-10 04:57:40

标签: java xml parsing dom

我习惯使用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循环深,要么更难使用。为什么这么复杂?我做错了什么?

1 个答案:

答案 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了解更多详情