views:

741

answers:

4

Any XPath like /NodeName/position() would give you the position of the Node w.r.t it's parent node.

There is no method on the XElement (Linq to XML) object that can get the position of the Element. Is there?

A: 
static int Position(this XNode node) {
  var position = 0;
  foreach(var n in node.Parent.Nodes()) {
    if(n == node) {
      return position;
    }
    position++;
  }
  return -1;
}
Michael Damatov
+3  A: 

You could use the NodesBeforeSelf method to do this:

    XElement root = new XElement("root",
  new XElement("one", 
   new XElement("oneA"),
   new XElement("oneB")
  ),
  new XElement("two"),
  new XElement("three")
 );

 foreach (XElement x in root.Elements())
 {
  Console.WriteLine(x.Name);
  Console.WriteLine(x.NodesBeforeSelf().Count()); 
 }

Update: If you really just want a Position method, just add an extension method.

public static class ExMethods
{
    public static int Position(this XNode node)
    {
     return node.NodesBeforeSelf().Count(); 
    }
}

Now you can just call x.Position(). :)

Bryant
Thanks, x.NodesBeforeSelf().Count() simply works, great.Wish they had called it Position on top of XElement class.
Vin
Overrule my previous comment. Check my answer below.
Vin
+3  A: 

Actually NodesBeforeSelf().Count doesn't work because it gets everything even of type XText

Question was about XElement object. So I figured it's

int position = obj.ElementsBeforeSelf().Count();

that should be used,

Thanks to Bryant for the direction.

Vin
A: 

Actually in the Load method of XDocument you can set a load option of SetLineInfo, you can then typecast XElements to IXMLLineInfo to get the line number.

you could do something like

var list = from xe in xmldoc.Descendants("SomeElem")
           let info = (IXmlLineInfo)xe
           select new 
           {
              LineNum = info.LineNumber,
              Element = xe
           }
Tim Jarvis
But that still doesn't give you the position with respect to the parent of a node. Isn't it just the line number?
Vin