【问题标题】:Very Simple xml to linq query非常简单的 xml 到 linq 查询
【发布时间】:2020-12-01 01:20:51
【问题描述】:

我是 Linq to XML 的新手(Linq 时期的新手)

我有一个非常简单的 XML 结构(我可以手动解析它,但我想学习 linq to xml)。

这是我的代码:

XElement approvalRequest = XElement.Load(xml);
string emailTo = (string)(approvalRequest.Descendants("to").First().Value);

这会抛出

无效操作异常:序列不包含值

然而,

string emailTo = (string) (approvalRequest.Descendants().First().Value) 

返回预期结果(因为'to'是第一个元素)

这是approvalRequest 的值(在 C# Watch 中查询)

<email xmlns="http://tempuri.org/XMLSchema.xsd">
  <to>:approver_email</to>
  <from>:my_email</from>
  <subject>:rm Code Review</subject>
  <body>
    Hi :approver_first_name
    
    Please review the code for :rm.  All modules are in SCM/MDSS/UAT/:rm
    
    Thanks,
    :my_name
    :my_email
    
  </body>
  <attachments></attachments>
</email>

看起来这应该是愚蠢的简单。我一定缺少一些基本的东西。

我也尝试过使用实际的 linq 查询来解决它,但总是得到空值。

同样来自 Watch 扩展 approvalRequest.Descendants() 产生:

【问题讨论】:

    标签: c# xml linq


    【解决方案1】:

    XML 有一个默认命名空间:xmlns="http://tempuri.org/XMLSchema.xsd"。

    这意味着每个 XML 元素都绑定到它。即使它不明确可见。

    请在下面找到如何处理它。

    为了方便,我只是使用.Parse() 方法而不是文件中的.Load() 方法。

    c#

    void Main()
    {
        XDocument xdoc = XDocument.Parse(@"<email xmlns='http://tempuri.org/XMLSchema.xsd'>
            <to>:approver_email</to>
            <from>:my_email</from>
            <subject>:rm Code Review</subject>
            <body>Hi :approver_first_name
            
            Please review the code for :rm.  All modules are in SCM/MDSS/UAT/:rm
            
            Thanks,
            :my_name
            :my_email</body>
            <attachments></attachments>
        </email>");
    
        XNamespace ns = xdoc.Root.GetDefaultNamespace();
    
        string emailTo = xdoc.Descendants(ns + "to").FirstOrDefault().Value;
    }
    

    【讨论】:

      【解决方案2】:

      正如@Yitzhak Khabinsky 提到的那样,您的方法存在的问题是您忽略了您的 xml 具有默认命名空间这一事实。

      作为他的方法的替代方法,您可以使用XName 类的LocalName (1) 字段。

      var parsedXml = XDocument.Load("sample.xml");
      var toValue = parsedXml.Descendants().FirstOrDefault(n => n.Name.LocalName == "to")?.Value;
      Console.WriteLine(toValue);
      
      • 使用Descendants 检索所有节点为XElements
      • 每个XElement 都有一个名为Name 的属性,类型为XName
      • 每个XName 都有一个LocalName 和一个Namespace 属性

      您可以检查 LocalName 或 ToString(正如 Yitzhak Khabinsky 建议的那样)。 ToString 是 overriden,如下所示:

      public override string ToString()
      {
          if (_ns.NamespaceName.Length == 0) return _localName;
          return "{" + _ns.NamespaceName + "}" + _localName;
      }
      

      【讨论】:

      • 嗨,彼得。谢谢。您在 Descendents/Xname/LocalName 等周围的 cmets 是最有启发性的。我使用了@Yitzhak Khabinsky 的解决方案,因为在我看来它更直接。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-03
      • 1970-01-01
      相关资源
      最近更新 更多