【问题标题】:Finding element in XDocument?在 XDocument 中查找元素?
【发布时间】:2012-01-17 15:06:14
【问题描述】:

我有一个简单的 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>

然而,

当我想到达“门乐队”并更改其 ID 时:

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

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

                            select c;
                             ...

query 没有结果

但是

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

有什么问题?

是否需要根目录的完整路径?

如果是这样,为什么不指定 AllBands 就可以工作?

XDocument 导航是否要求我了解完整级别的结构直至所需元素?

【问题讨论】:

    标签: c# .net xml linq-to-xml


    【解决方案1】:

    Elements() 只会检查直接子元素——在第一种情况下是根元素,在第二种情况下是根元素的子元素,因此在第二种情况下你会得到匹配。如果您只想要任何匹配的后代,请改用Descendants()

    var query = from c in xmlFile.Descendants("Band") select c;
    

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

    <Band>
      <BandProperties Name ="Doors" ID="222" started="1968" />
      <Description>regular Band<![CDATA[lalala]]></Description>
      <Last>1</Last>
      <Salary>2</Salary>
    </Band>
    

    【讨论】:

    • 是的,我知道它应该是名称元素,里面应该是披头士/门......谢谢你的解释。这只是一个让我测试的 Quick Xml,我还没有深入思考过一个例子
    • 谢谢!如果您可以添加一些带有命名空间的示例,那该多好。喜欢XNamespace xsiNs = "http://www.w3.org/2001/XMLSchema-instance"; var element = productionPackage.Descendants(xsiNs + "ElementToFind")
    【解决方案2】:

    你可以这样做:

    xml.Descendants().SingleOrDefault(p => p.Name.LocalName == "Name of the node to find")
    

    其中 xml 是一个 XDocument。

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

    【讨论】:

      【解决方案3】:

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

      xmlFile.Root.Elements("Band")
      

      如果您想在文档中的任何位置查找元素,请改用Descendants

      xmlFile.Descendants("Band")
      

      【讨论】:

        【解决方案4】:

        问题是Elements 只接受你调用它的任何direct 子元素。如果您想要所有后代,请使用Descendants 方法:

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

        【讨论】:

          【解决方案5】:

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

          在这种情况下,我发现手动搜索元素是一种更安全的选择,如以下 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?forum=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;
          }
          

          然后你可以这样调用:

          XElement element = GetElement(doc,"Band");
          

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

          【讨论】:

            【解决方案6】:

            Elements() 方法返回一个包含当前节点所有子元素的IEnumerable&lt;XElement&gt;。对于 XDocument,该集合仅包含 Root 元素。因此需要以下内容:

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

            【讨论】:

              【解决方案7】:

              Sebastian 的答案是在检查 xaml 文档时对我有用的唯一答案。如果像我一样,您想要一个所有元素的列表,那么该方法看起来很像上面塞巴斯蒂安的答案,但只是返回一个列表......

                  private static List<XElement> GetElements(XDocument doc, string elementName)
                  {
                      List<XElement> elements = new List<XElement>();
              
                      foreach (XNode node in doc.DescendantNodes())
                      {
                          if (node is XElement)
                          {
                              XElement element = (XElement)node;
                              if (element.Name.LocalName.Equals(elementName))
                                  elements.Add(element);
                          }
                      }
                      return elements;
                  }
              

              这样称呼它:

              var elements = GetElements(xamlFile, "Band");
              

              或者对于我想要所有 TextBlocks 的 xaml 文档,这样称呼它:

              var elements = GetElements(xamlFile, "TextBlock");
              

              【讨论】:

                猜你喜欢
                • 2020-03-29
                • 2013-05-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-01-24
                相关资源
                最近更新 更多