tags:

views:

26

answers:

1

Hi,

These two LINQ to XML methods seem to be doing the same thing. Would like to know the difference between the two.

var xdoc = XDocument.Load(filename);

xdoc.Root.FirstNode.ElementsAfterSelf();
xdoc.Root.FirstNode.NodesAfterSelf();

Both return methods return

<Title Name="Cooking with Computers: Surreptitious Balance Sheets" Price="11.9500">
  <Authors>
    <Author Name="O'Leary, O'Leary" />
    <Author Name="MacFeather, MacFeather" />
  </Authors>
</Title>  
<Title Name="You Can Combat Computer Stress!" Price="2.9900">
  <Authors>
    <Author Name="Green, Green" />
  </Authors>
</Title>  

Here is the XML

<PubsDatabase>
  <Title Name="The Busy Executive's Database Guide" Price="19.9900">
    <Authors>
      <Author Name="Green, Green" />
      <Author Name="Bennet, Bennet" />
    </Authors>
  </Title>
  <Title Name="Cooking with Computers: Surreptitious Balance Sheets" Price="11.9500">
    <Authors>
      <Author Name="O'Leary, O'Leary" />
      <Author Name="MacFeather, MacFeather" />
    </Authors>
  </Title>
  <Title Name="You Can Combat Computer Stress!" Price="2.9900">
    <Authors>
      <Author Name="Green, Green" />
    </Authors>
  </Title>
</PubsDatabase>
+1  A: 

Nodes will return things like text nodes as well as elements, basically. For example:

using System;
using System.Xml;
using System.Xml.Linq;

namespace Test
{
    class Test
    {
        static void Main()
        {
            XElement element = new XElement("root",
                new XElement("child1", "text1"),
                "text directly in root",
                new XElement("child2"),
                new XElement("child3", "text3"));

            XElement child1 = element.Element("child1");
            var nodes = child1.NodesAfterSelf();
            foreach (var node in nodes)
            {
                Console.WriteLine(node.NodeType);
            }
        }
    }
}

This prints

Text
Element
Element

A few things to note:

  • It's not including the nodes within itself
  • It's not recursing (it doesn't show the text node of child3)
  • It does include the text node directly after it, which ElementsAfterSelf wouldn't.

As a side note, attributes don't count as nodes in LINQ to XML. From the XNode documentation:

Represents the abstract concept of a node (one of: element, comment, document type, processing instruction, or text node) in the XML tree.

This is in contrast to most XML APIs.

Jon Skeet
I've added an attribute to child2 and ElementsAfterSelf() does not seem to be retrieving this.
Sir Psycho
@Sir Psycho: No, it wouldn't, for two reasons: 1) Attributes aren't nodes in LINQ to XML, as per the bottom of my answer. 2) it doesn't recurse - it won't show nodes *within* child2, as per my second bullet point.
Jon Skeet
I didn't realise attributes were considered to be 'deeper' than the node it's declared on.
Sir Psycho
@Sir Psycho: Think of the XML structure as a tree. If an attribute didn't count as being "under" the element it's declared in, how would you know which one it belonged to?
Jon Skeet
I assumed it was part of the element. Never mind, point taken.
Sir Psycho