Shane
Shane

Reputation: 77

SelectSingleNode Node InnerText property not correct

I am attempting to get the value of a specific node for each parent element found. In the example I want to return each students First Name. Instead I am getting the first elements name in each instance. The InnerText of a Student is correct but the InnerText of FirstName is always Alex.

var xml = @"<School>
                <Students>
                    <Student>
                        <FirstName>Alex</FirstName>
                        <LastName>Smith</LastName>
                        <Grade>11</Grade>
                    </Student>
                    <Student>
                        <FirstName>Joanne</FirstName>
                        <LastName>Robins</LastName>
                        <Grade>12</Grade>
                    </Student>
                    <Student>
                        <FirstName>Steve</FirstName>
                        <LastName>Baker</LastName>
                        <Grade>11</Grade>
                    </Student>
                </Students>
                <Teachers>
                    <Teacher>
                        <FirstName>George</FirstName>
                        <LastName>Roberts</LastName>
                        <Grade>11</Grade>
                    </Teacher>
                    <Teacher>
                        <FirstName>Amanda</FirstName>
                        <LastName>Walker</LastName>
                        <Grade>12</Grade>
                    </Teacher>
                    <Teacher>
                        <FirstName>Tracey</FirstName>
                        <LastName>Smith</LastName>
                        <Grade>12</Grade>
                    </Teacher>
                </Teachers>
            </School>";

var doc = new XmlDocument();
doc.LoadXml(xml);

var resourceTypeNodes = doc.GetElementsByTagName("Student");
var resourceTypesIterator = resourceTypeNodes.GetEnumerator();

while (resourceTypesIterator != null && resourceTypesIterator.MoveNext())
{
    var resourceTypeNode = resourceTypesIterator.Current as XmlNode;
    var typeNameElement = resourceTypeNode.SelectSingleNode("//FirstName");

    Console.WriteLine(resourceTypeNode.InnerXml);
    Console.WriteLine(typeNameElement.InnerText);
}

This is the output of the above code.

<FirstName>Alex</FirstName><LastName>Smith</LastName><Grade>11</Grade>
Alex
<FirstName>Joanne</FirstName><LastName>Robins</LastName><Grade>12</Grade>
Alex
<FirstName>Steve</FirstName><LastName>Baker</LastName><Grade>11</Grade>
Alex

What am I missing?

Upvotes: 1

Views: 675

Answers (1)

Adriano Repetti
Adriano Repetti

Reputation: 67090

Because you're using //FirstName XPath expression, that will always return first node from root, it doesn't matter if you invoke on children. Just change this:

var typeNameElement = resourceTypeNode.SelectSingleNode("//FirstName");

To this:

var typeNameElement = resourceTypeNode.SelectSingleNode("FirstName");

Moreover is there any specific reason you're manually using IEnumerator? You may simplify your code with foreach:

foreach (XmlNode resourceTypeNode in doc.GetElementsByTagName("Student"))
{
    var typeNameElement = resourceTypeNode.SelectSingleNode("FirstName");

    Console.WriteLine(resourceTypeNode.InnerXml);
    Console.WriteLine(typeNameElement.InnerText);
}

Upvotes: 1

Related Questions