在XDocument中查找元素?

Roy*_*mir 49 .net c# xml linq-to-xml

我有一个简单的XML

<AllBands>
  <Band>
    <Beatles ID="1234" started="1962">greatest Band<![CDATA[lalala]]></Beatles>
    <Last>1</Last>
    <Salary>2</Salary>
  </Band>
  <Band>
    <Doors ID="222" started="1968">regular Band<![CDATA[lalala]]></Doors>
    <Last>1</Last>
    <Salary>2</Salary>
  </Band>
</AllBands>
Run Code Online (Sandbox Code Playgroud)

但是,

当我想要到达"门乐队"并更改其ID时:

  using (var stream = new StringReader(result))
            {
                XDocument xmlFile = XDocument.Load(stream);

                var query = from c in xmlFile.Elements("Band")

                            select c;
                             ...
Run Code Online (Sandbox Code Playgroud)

query 没有结果

如果我xmlFile.Elements().Elements("Band")这样写 ,它会找到它.

问题是什么 ?

需要来自Root的完整路径吗?

如果是这样,为什么它没有指定就可以工作AllBands

XDocument导航是否要求我知道所需元素的完整级别结构?

Bro*_*ass 80

Elements()将仅检查直接子项 - 在第一种情况下是根元素,在第二种情况下是根元素的子项,因此在第二种情况下得到匹配.如果您只想使用任何匹配的后代Descendants():

var query = from c in xmlFile.Descendants("Band") select c;
Run Code Online (Sandbox Code Playgroud)

另外我建议你重新构造你的Xml:波段名称应该是一个属性或元素值,而不是元素名称本身 - 这使得查询(以及对此问题的模式验证)更加困难,例如:

<Band>
  <BandProperties Name ="Doors" ID="222" started="1968" />
  <Description>regular Band<![CDATA[lalala]]></Description>
  <Last>1</Last>
  <Salary>2</Salary>
</Band>
Run Code Online (Sandbox Code Playgroud)


Fra*_*ein 27

你可以这样做:

xml.Descendants().SingleOrDefault(p => p.Name.LocalName == "Name of the node to find")
Run Code Online (Sandbox Code Playgroud)

其中xml是XDocument.

请注意,属性Name返回一个具有LocalName和Namespace的对象.这就是为什么如果要按名称进行比较,必须使用Name.LocalName.


Mar*_*ers 25

您应该使用Root引用根元素:

xmlFile.Root.Elements("Band")
Run Code Online (Sandbox Code Playgroud)

如果要在文档中的任何位置查找元素,请使用Descendants:

xmlFile.Descendants("Band")
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 6

问题是Elements只接受你所称的任何直接子元素.如果您想要所有后代,请使用以下Descendants方法:

var query = from c in xmlFile.Descendants("Band")
Run Code Online (Sandbox Code Playgroud)


小智 6

我在处理大而复杂的 XML 文件时的经验是,有时元素和后代似乎都无法检索特定元素(我仍然不知道为什么)。

在这种情况下,我发现一个更安全的选择是手动搜索元素,如以下 MSDN 帖子所述:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/3d457c3b-292c-49e1-9fd4-9b6a950f9010/how-to-get-tag-name-of-xml-by-using-xdocument?论坛=csharpgeneral

简而言之,您可以创建一个 GetElement 函数:

private XElement GetElement(XDocument doc,string elementName)
{
    foreach (XNode node in doc.DescendantNodes())
    {
        if (node is XElement)
        {
            XElement element = (XElement)node;
            if (element.Name.LocalName.Equals(elementName))
                return element;
        }
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样调用:

XElement element = GetElement(doc,"Band");
Run Code Online (Sandbox Code Playgroud)

请注意,如果没有找到匹配的元素,这将返回null