Using Linq to XML, how can I select the elements that have exactly x number of parent elements?

I am trying to use Linq to XML in my c# program to extract element names from an auto-generated XSD file. This means I cannot do queries based on element names/ contents, and instead need to find elements based on their position in the xsd. I'm trying to do this with a function that returns an element's 'depth'. Somehow, if I use it in my query, I get not only the elements I need but also all underlying elements/attributes. I am guessing I need an "exclude" function in some way, but I don't know how to do this. This is the code I have at the moment:

        static public void XsdReader()
        {
            var xsd = XDocument.Load(@"c:\XsdToLoad.xml");
            var elementsAtDepthEight = from e in xsd.Descendants()
                where GetElementDepth(e) == 8
                select e;


            foreach (var p in elementsAtDepthEight)
            {
                Console.WriteLine(p.ToString());
            }

        }
        static int GetElementDepth(XElement element)
        {
            int result = 1;

            //always return 1 as the root node has depth of 1.
            //in addition, return the maximum depth returned by this method called on all the children.
            if (element.Parent != null)
            {
                result += GetElementDepth(element.Parent);
            }
            return result;
        }
Jon Skeet
people
quotationmark

The simplest way to measure "depth" is to count ancestors:

var elementsAtDepth8 = xsd.Descendants()
                          .Where(x => x.Ancestors().Count() == 8);

No need to write your own recursive code at all.

Another slightly odd alternative would be to write:

var elementsAtDepth = xsd.Elements()
                         .Elements()
                         .Elements()
                         .Elements()
                         .Elements()
                         .Elements()
                         .Elements()
                         .Elements();

You could obviously write a pair of recursive methods to do this:

public static IEnumerable<XElement> ElementsAtDepth(this XNode node, int depth)
{
    return node.Elements().ElementsAtDepth(depth - 1);
}

public static IEnumerable<XElement> ElementsAtDepth(
    this IEnumerable<XElement> elements, int depth)
{
    // TODO: Validate that depth >= 0
    return depth == 0 ? elements : elements.Elements().ElementsAtDepth(depth - 1);
}

people

See more on this question at Stackoverflow