简体   繁体   中英

SelectSingleNode seems to search parents and siblings

I also think I'm confused about XPath usage. I'm new to C# and XPath, so please be patient with me ;)

First, my XML file that I'm testing with:

<?xml version="1.0" encoding="ISO-8859-1"?>
<testroot>
    <testnode>
        <name>Test Node 1</name>
        <things>
            <thing>
                <number>One</number>
            </thing>
            <thing>
                <number>Two</number>
            </thing>
        </things>
    </testnode>
    <testnode>
        <name>Test Node 2</name>
        <things>
            <thing>
                <number>Three</number>
            </thing>
            <thing>
                <number>Four</number>
            </thing>
        </things>
    </testnode>
    <testnode>
        <name>Test Node 3</name>
        <things>
            <thing>
                <number>Five</number>
            </thing>
        </things>
    </testnode>
</testroot>

So first I want to get the "testnode" that contains a "name" I'm interested in. So I did the following, which worked correctly:

XmlNode testRoot = xmlDoc.DocumentElement.SelectSingleNode("/testroot/testnode[name=\"Test Node 1\"]");

Now I want to get all of the nodes under it that contain a "number" element. According to my reading, I should be able to do this:

XmlNodeList testNodes = testRoot.SelectNodes("number");

But that yields an empty list. The only way I got any results was to use //:

XmlNodeList testNodes = testRoot.SelectNodes("//number");

The problem is that seems to search all of the siblings and parents of the testRoot. When I print everything out I get every node in the file that contains "number":

txtOutput.InnerHtml += "<p>" + testRoot.FirstChild.InnerText + "</p>";

foreach (XmlNode node in testNodes)
{
    txtOutput.InnerHtml += node.InnerText + "<br />";
}
 Test Node 1 One Two Three Four Five 

This behavior confuses me. Am I using XPaths improperly, or does it normally search from the absolute root no matter which XmlNode you start with?

You're trying to find direct child nodes called number . There aren't any of those - just one things element. If you want descendants, say so:

XmlNodeList testNodes = testRoot.SelectNodes("descendant::number");

The version with "//number" basically looks through all nodes in the document, hence your other result.

Having said all this, if you're using .NET 3.5 or higher I'd just use LINQ to XML and do all the querying in that. It's a much nicer API, IMO :)

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