LINQ to XML:我如何获取XElement的直接子元素?

21
Dim xml = <Root>
            <Parent id="1">
              <Child>Thomas</Child>
            </Parent>
            <Parent id="2">
              <Child>Tim</Child>
              <Child>Jamie</Child>
            </Parent>
          </Root>

Dim parents = xml.Elements
在这种情况下,children包括所有的Parent元素和Child元素。要抓取<Root>的直接子孙元素,最好的方法是什么?我应该编写一个LINQ查询来选择父级为<Root>的元素吗?还是有一些内置的方法我错过了可以帮我实现这个功能? 编辑: 我在XElement.ElementsXElement.Descendants之间有些困惑。正如Ruben Bartelink指出的那样,XElement.Elements将给我我正在寻找的东西。

你能在这里编辑你最终使用的实际咒语吗?顺便说一句,请下载LINQPad并尝试一下——它非常适合测试像这样的东西。请查看http://www.dimecasts.net/Casts/ByTag/LinqPad上的示例。 - Ruben Bartelink
5个回答

20

XElement.Elements获取子元素的集合。例如...

var s = @"<root>
             <e1>
                 <e2>
                 </e2>
             </e1>
             <e1>
                 <e2>
                 </e2>
             </e1>
             <e1>
                 <e2>
                 </e2>
             </e1>
          </root>";

var doc = XElement.Load( new StringReader(s) );

Console.WriteLine( doc.Elements().Count() ); // 3
Console.WriteLine( doc.Descendants().Count()); //6

18

执行摘要 - 您想要:

xml.Elements.Select(function(element) new XElement(element.Name,element.Attributes))

第一个答案:

XElement.Descendants,或者这是个诡计?:P 这里有一个使用Descendants的示例

修正后的答案,感谢Tormod -- 感觉有点不对劲!:

Elements 给出直接的子代,正如你所寻找的那样。 Descendants 给出完整的层次结构 [就像你声称 Elements 所做的那样]。(我链接的示例清楚地说明了这一点。对于混淆表示歉意!

因此,最后,你要寻找的是(这次是 VB):

Dim xml = <Root>
        <Parent id="1">
          <Child>Thomas</Child>
        </Parent>
        <Parent id="2">
          <Child>Tim</Child>
          <Child>Jamie</Child>
        </Parent>
      </Root>

REM All nodes two levels down in the hierarchy
Dim level2Nodes = xml.Elements.SelectMany(function(element) element.Elements)
level2Nodes.Dump

REM All Child nodes, no matter where they are:
Dim children = xml.Descendants("Child")

每个元素都会生成3个不同原因的```元素,这在REMs中有所涵盖。
(将上述内容直接粘贴到VB语句模式下的LINQPad中)
我现在明白可能会让你感到困惑的是-当你使用Elements并在可视化器中查看时,你仍然看到的是子元素:
Dim parents = xml.Elements

如果你只需要实际的名称,可以使用类似以下的方式:

Dim parentNames = xml.Elements.Select(function(element) element.Name)

请注意,在每种情况下,您都会获得两个结果。
如果您真的想剥离子元素,则需要使用以下代码:
Dim parentElements = xml.Elements.Select(function(element) new XElement(element.Name,element.Attributes))

你能否详细说明你真正想找的是什么?


3
Descendants() 方法获取所有后代元素,而不仅仅是直接后代。在这种情况下,“root”的后代将包括所有子元素。 - Tormod
@Tormod,你确定吗?看看这个例子?如果不明白,后代和元素之间有什么区别? - Ruben Bartelink

4
使用Linq,我们可以做到这一点。
string s = "<Root><Parent id=\"1\"><Child>Thomas</Child></Parent><Parent id=\"2\"><Child>Tim</Child><Child>Jamie</Child></Parent></Root>";
XDocument xdoc = XDocument.Parse(s);
foreach (XElement DirectChild in xdoc.Descendants().Where(child => child.Parent == xdoc.Root))
{
//Do stuff here
}

希望这可以帮到您。谢谢。

0
如果所有直接后代都具有相同的已知元素名称,并且此元素名称不能出现在另一个级别中,则可以使用xml.Descendants("Parent")。

-1

为什么不使用XPath?

Dim myXML As var = New XmlDocument()
myXML.Load(myXML.xml)

For Each node As XmlNode In myXML.SelectNodes("//")
    Dim myVar As var = node.SelectSingleNode("Parent").InnerText
Next

请带着一点点保留看待 - 我只是把它从 C# 转换成了 VB。


XLinq非常整洁,一旦克服了要使用哪种方法的困惑,就没有问题啦:P - Ruben Bartelink
1
好的,我得去研究一下了。如果你们都开始使用XLinq,那么XPath可能已经过时了! - Daniel May

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接