使用Linq to XML,我如何选择恰好有x个父元素的元素?

本文关键字:元素 选择 XML to Linq 何选择 使用 | 更新日期: 2023-09-27 18:13:57

我试图在我的c#程序中使用Linq to XML从自动生成的XSD文件中提取元素名称。这意味着我不能基于元素名称/内容进行查询,而是需要根据元素在xsd中的位置查找元素。我试图用一个返回元素"深度"的函数来做到这一点。不知何故,如果我在查询中使用它,我不仅得到我需要的元素,而且得到所有底层元素/属性。我猜我需要一个"排除"功能在某种程度上,但我不知道如何做到这一点。这是我现在的代码:

        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;
        }

使用Linq to XML,我如何选择恰好有x个父元素的元素?

衡量"深度"最简单的方法是计算祖先:

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

根本不需要编写自己的递归代码。

另一个稍微奇怪的替代方法是:

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

你显然可以写一对递归方法来做这件事:

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);
}