简体   繁体   中英

How to find a child element with specific attribute value

I'm used to C++ libraries for xml parsing, namely rapidxml and tinyxml. The java built in DOM parser makes absolutely no sense to me. After some struggle I was able to store the root node I need, but now I want to find a tag with a specific id.

Here is a sample 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>

I have the <story> node stored in a Node instance. From there, I want to find nodes wiith a specific id (let's say the 'n3' node).

I want to use this method:

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;
}

This would be my way to go with a C++ library, but this is very far from working... I don't understand why I have to typecast for such simple task. Why can't the Node have a method to get attributes with specifying the attribute name. The getFirstChild() doesn't even seem to return the first child...

The wrapper classes I found online are either 30 loops deep, or even harder to use. Why is this so complicated? What am I doing wrong?

Why the API is so...awesome...will come down to why and how it was designed. The solution, may be simpler then you think.

One of the features available to you is the XPath implementation, it's touted as a query language for XML.

So, instead of trying to loop through each node and each child node, you could simply use something like //*[@id='n1'] to find any node with the id attribute that equals n1 (for example).

Using your example XML and the following code...

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();
}

This outputted

Found 1 matches

Take a look at XPath for some more details

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM