LINQ to XML:我如何只获得XElement的直接后代?

时间:2009-08-04 11:14:14

标签: .net xml vb.net linq-to-xml

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查询来选择parent = <Root>的元素吗?或者是否有一些我遗漏的内置方法可以为我解决这个问题?

编辑:我在XElement.ElementsXElement.Descendants之间产生了一些混淆。正如Ruben Bartelink所指出的那样,XElement.Elements会给我我正在寻找的东西。

5 个答案:

答案 0 :(得分:18)

执行摘要 - 您想:

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

第一个回答:

  

XElement.Descendants,还是一个技巧问题? :P There's an example of usage of Descendants here

修改回答,谢谢Tormod - 有些事情确实有问题!:

元素提供直接后代,正如您所寻找的那样。后代给出了完整的等级[正如你所说的元素所做的那样]。 (我联系的例子清楚地说明了这一点。为混乱道歉!

所以,最后,你要找的是(这次是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")

由于REMs中所述的不同原因,每个元素都会产生3个```元素。

(在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))

你可以扩展你的问题以显示你真正想要的东西吗?

答案 1 :(得分:17)

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

答案 2 :(得分:3)

使用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
}

希望这会有所帮助。谢谢。

答案 3 :(得分:0)

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

答案 4 :(得分:-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。