.net LINQ to XML:如何只获取 XElement 的直接后代?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1226899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:06:42  来源:igfitidea点击:

LINQ to XML: how do I get only direct descendants of an XElement?

.netxmlvb.netlinq-to-xml

提问by Rob Sobers

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

In this case, childrenincludes all the Parent elements and all of the Child elements. What's the best way to grab only the direct descendantsof <Root>?

在这种情况下,children包括所有父元素和所有子元素。获取的直系后代的最佳方法是<Root>什么?

Should I write a LINQ query that selects elements where parent = <Root>? Or is there some built-in method I'm missing that can get this for me?

我应该编写一个 LINQ 查询来选择 parent = 的元素<Root>吗?或者是否有一些我缺少的内置方法可以为我提供这个?

EDIT:I had some confusion between XElement.Elementsand XElement.Descendants. As Ruben Bartelink pointed out, XElement.Elementswill give me exactly what I was looking for.

编辑:我在XElement.Elements和之间有些混淆XElement.Descendants。正如 Ruben Bartelink 所指出的,XElement.Elements会给我正是我想要的。

回答by Ruben Bartelink

Exec summary - you want:

执行摘要 - 你想要:

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

First answer:

第一个回答:

XElement.Descendants, or is it a trick question ? :P There's an example of usage of Descendants here

XElement.Descendants,或者这是一个技巧问题?:P这里有一个使用后代的例子

Revised answer, thanks Tormod -- something did feel wrong!:

修改后的答案,感谢 Tormod——确实感觉有些不对劲!:

Elements gives direct descendants, as you're looking for. Descendants gives the full hierarchy [as you are alleging Elements does]. (The example I linked to makes this clear. Apologies for the confusion!

Elements 提供您正在寻找的直接后代。后代给出了完整的层次结构[正如你所说的元素所做的那样]。(我链接到的示例清楚地说明了这一点。为造成的混乱道歉!

So, finally, what you're looking for is (this time in VB):

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

Each of which will yield you the 3 ``` elements for different reasons as covered in the REMs.

由于 REM 中涵盖的不同原因,每个元素都会为您生成 3 个 ``` 元素。

(Paste the above directly into LINQPadin VB statement mode)

(在VB语句模式下直接将以上内容粘贴到LINQPad中)

I now see what might be confusing you - when you use Elements and look at it in a visualiser, you are still seeing the children:-

我现在看到什么可能让您感到困惑 - 当您使用 Elements 并在可视化器中查看它时,您仍然看到孩子:-

Dim parents = xml.Elements

If you only want the actual names, you can use something like:

如果您只想要实际名称,则可以使用以下内容:

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

Note that in each of these cases, you are getting two results.

请注意,在每种情况下,您都会得到两个结果。

If you really want to strip out the chidren, you want:

如果你真的想去掉儿童,你需要:

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

Can you extend your question to show what you're really looking for?

您能否扩展您的问题以显示您真正在寻找什么?

回答by JP Alioto

XElement.Elementsgets the collection of child elements. For example ...

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

回答by Mohamed Alikhan

Using Linq we can do that.

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

Hope this helps. Thank you.

希望这可以帮助。谢谢你。

回答by Sharon

If all direct descendants have the same known element name, and this element name can't appear in another level, you can use xml.Descendants("Parent").

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

回答by Daniel May

Why not use XPath?

为什么不使用 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

Take this with a pinch of salt - I just converted it from C# to VB.

加一点盐 - 我只是将它从 C# 转换为 VB。