【问题标题】:Getting an XML node using LINQ使用 LINQ 获取 XML 节点
【发布时间】:2010-03-25 12:30:17
【问题描述】:

不知何故,使用 linq 我无法在一开始就用这个 CUF 字段对其进行测试:

<NFe>
    <infNFe versao="1.0" Id="NFe0000000000">
        <ide>
             <cUF>35</cUF>
             <!--...-->
        </ide>
    </infNFe>
</NFe>

使用以下代码:

XDocument document = XDocument.Load(@"c:\nota.xml");
            var query = from NFe in document.Descendants("NFe")
                        select new
                        {
                            cuf = NFe.Element("infNFe").Element("ide").Element("cUF").Value
                        };

整个 XML 加载到文档中(选中),但 NFe.cuf 什么也没给我。我猜节点内部的参数搞砸了..

如何使用 linq 获得这个“cuf”?
如果我想要 infNFe 中的 Id 参数怎么办?

--[编辑]--

我忘了给出“开头的愚蠢的url”,结果是它是NAMESPACE,(火狐贡献的xml的命名空间不显示)

现在可以了:

        XNamespace ns = "http://www.portalfiscal.inf.br/nfe";
        XElement root = XElement.Load(@"c:\nota.xml");

        textBox1.Text = root.Element(ns + "infNFe").Element(ns + "ide").Element(ns + "cUF").Value;

有没有办法在某个地方设置命名空间,而不需要把它放在每个字段调用中?

【问题讨论】:

  • 您没有发布有效的 XML(缺少 &lt;/ide&gt;&lt;/infNFe&gt;&lt;/NFe&gt;)。看起来像一个愚蠢的请求,但看着它(非缩进)让人认为他们都是根。
  • @Alex - 编辑 XML 以使其更清晰。
  • 嗯,我确实提到这是我的 XML 的开始,寻址节点只需要它的名称和父节点,我只想展示它的样子,而不是提供有效的 XML .
  • 您仍然没有正确缩进 XML - ideinfNFe 的子代,而不是兄弟姐妹

标签: c# .net xml linq


【解决方案1】:

您并不真正需要完整的 LINQ 查询 - 一个单行就可以了:

string cuf = document.Root.Element("infNFe").Element("ide").Element("cUF").Value;
// cuf = 35

ID 也一样:

string id = document.Root.Element("infNFe").Attribute("Id").Value;
// id = NFe0000000000

【讨论】:

    【解决方案2】:

    您正在查看 document.Descendants,它是根目录中的所有元素。

    document.Descendants 在您的情况下将包含 infNFe、ide、cUF ... 这就是为什么在集合中找不到根的原因。

    尝试改用 document.Root。

    【讨论】:

    • 不可能在查询中就地使用 document.Root,因为返回单个节点,而 Descendants 返回节点集合。但是,正如我在回答中所展示的那样,OP 可以将 document.Root 与单行代码一起使用。
    • 好点,我想我没有详细说明您将如何使用 document.Root
    【解决方案3】:

    试试query.SingleOrDefault();

    【讨论】:

      【解决方案4】:

      您可以使用 XPath:

      using System;
      using System.Xml.Linq;
      using System.Xml.XPath;
      
      class Program
      {
          static void Main(string[] args)
          {
              var doc = XDocument.Load(@"c:\nota.xml");
              var cuf = doc.XPathSelectElement("//cUF");
              if (cuf != null)
              {
                  Console.WriteLine(cuf.Value);
              }
      
              var infNFe = doc.XPathSelectElement("//infNFe");
              if (infNFe != null)
              {
                  var id = infNFe.Attribute("Id");
                  if (id != null) 
                  {
                      Console.WriteLine(id.Value);
                  }
              }
      
          }
      }
      

      鉴于此 XML:

      <?xml version="1.0"?>
      <NFe>
        <infNFe versao="1.0" Id="NFe0000000000">
          <ide>
            <cUF>35</cUF>
          </ide>
        </infNFe>
      </NFe>
      

      【讨论】:

        【解决方案5】:

        实际上,在运行您的代码时,我没有发现任何问题。 我已经完成了以下操作:

        XDocument document = XDocument.Load(@"c:\temp\nota.xml");
        var query = from NFe in document.Descendants("NFe")
                    select new
                    {
                        cuf = NFe.Element("infNFe").Element("ide").Element("cUF").Value,
                        infId = NFe.Element("infNFe").Attribute("Id").Value
                    };
        
        foreach(var v in query)
            Console.WriteLine(v.cuf + " " + v.infId);
        

        给定以下 xml:

        <NFe> 
        <infNFe versao="1.0" Id="NFe0000000000"> 
        <ide> 
        <cUF>35</cUF> 
        </ide>
        </infNFe>
        </NFe> 
        

        它输出:

        35 NFe0000000000
        

        【讨论】:

          【解决方案6】:

          编辑:使用 XElement,它更容易。

          现在您正在使用命名空间,因此您还需要使用 XNamespace 指定它们

          如果您不确定问题出在哪里,只需将您的查询拆分为多行,如下所示,以便您可以逐步确定错误发生的位置。

          XNamespace ns = "http://www.somewebsite.com";
          XElement root = XElement.Load(@"c:\nota.xml");
          var infNFe = root.Element(ns + "infNFe");
          var ide = infNFe.Element(ns + "ide");
          var cUF = ide.Element(ns + "cUF");
          var value = cUF.Value;
          

          为了澄清命名空间问题,如果你有类似 XML

          <a xmlns="namespace">
              <b>123</b>
          </a>
          

          那么a.Element("b") 不存在。您需要使用命名空间namespace 询问元素 b。就像 C# 中其他任何地方的命名空间一样 - 它们类似于维度。你正在寻找正确的道路,但在错误的维度。

          【讨论】:

          • 好吧,它起作用了,但是我每次调用字段时都必须输入 nd + "field" 吗?我不能在命名空间设置的地方安装一个传统的单线吗?顺便说一句,谢谢你
          • 当我第一次开始使用 LINQ 和 XML 时,我问了一个类似的问题,但实际上这种方式很有意义。根据我的经验,您总是需要指定命名空间。没什么大不了的。
          • 不知何故..是的..检查新的编辑。我已经用给定的 ns+field 编写了单行代码。看起来还不错,因为它只是一个函数。
          猜你喜欢
          • 2019-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多