C# 使用linq查询从XML中提取值

C# 使用linq查询从XML中提取值,c#,xml,linq,C#,Xml,Linq,linq和XML新手,正在寻找返回值的方法 作为一个列表,然后将这些值连接到一个字符串中 XML格式如下: <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <Document xmlns='urn:iso:std:iso:20022:tech:xsd:pain.002.001.03' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> <C

linq和XML新手,正在寻找返回值的方法
作为一个列表,然后将这些值连接到一个字符串中

XML格式如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Document xmlns='urn:iso:std:iso:20022:tech:xsd:pain.002.001.03' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
  <CstmrPmtStsRpt>
    <GrpHdr>
      <MsgId>21233519</MsgId>
      <CreDtTm>2018-11-29T09:28:00</CreDtTm>
      <InitgPty>
        <Nm>Standard Bank SA</Nm>
        <Id>
          <OrgId>
            <BICOrBEI>SBZAZAJJXXX</BICOrBEI>
          </OrgId>
        </Id>
      </InitgPty>
    </GrpHdr>
    <OrgnlGrpInfAndSts>
      <OrgnlMsgId>Domestic Base-612742-300749</OrgnlMsgId>
      <OrgnlMsgNmId>PAIN.001.001.03</OrgnlMsgNmId>
      <OrgnlCreDtTm>2018-11-29T12:23:06</OrgnlCreDtTm>
      <OrgnlNbOfTxs>1</OrgnlNbOfTxs>
      <OrgnlCtrlSum>17500.00</OrgnlCtrlSum>
      <GrpSts>RJCT</GrpSts>
      <StsRsnInf>
        <Rsn>
          <Cd>NARR</Cd>
        </Rsn>
        <AddtlInf>Duplicate File</AddtlInf>
        <AddtlInf>Error: 6789</AddtlInf>
        <AddtlInf>Not Processed</AddtlInf>
      </StsRsnInf>
    </OrgnlGrpInfAndSts>
  </CstmrPmtStsRpt>
</Document>

但这只返回第一个值“Duplicate File”。如何解决此问题?

您需要访问
StsRsnInf
的子元素:

var info = doc.Descendants(ns + "CstmrPmtStsRpt")
            .Descendants(ns + "OrgnlGrpInfAndSts")
            .Descendants(ns + "StsRsnInf")                                       
            .SelectMany(r => r.Elements(ns + "AddtlInf").Select(s => new
            {
              Info = s.Value
            })).ToList();
通过使用
元素
(不带尾随的s),您只能访问单个元素而不是多个元素,因此您的结果只包含第一个元素的值


通过使用而不是
Select
可以从子枚举返回多个元素。

您需要访问
StsRsnInf
的子元素:

var info = doc.Descendants(ns + "CstmrPmtStsRpt")
            .Descendants(ns + "OrgnlGrpInfAndSts")
            .Descendants(ns + "StsRsnInf")                                       
            .SelectMany(r => r.Elements(ns + "AddtlInf").Select(s => new
            {
              Info = s.Value
            })).ToList();
通过使用
元素
(不带尾随的s),您只能访问单个元素而不是多个元素,因此您的结果只包含第一个元素的值


通过使用而不是
Select
可以从子枚举返回多个元素。

在代码中,
r.Element
将始终返回集合的第一个元素。 相反,尝试使用
r.Elements
,这将返回“AddtlInf”元素的集合


有关这方面的详细信息,请查看此

在代码中,
r.Element
将始终返回集合的第一个元素。 相反,尝试使用
r.Elements
,这将返回“AddtlInf”元素的集合

有关这方面的详细信息,请查看此

您可以在Linq中使用

var result = (string)xdoc.Descendants("member")
                         .FirstOrDefault(x => (string)x.Element("name") == "responseCode")
                         ?.Element("value");

    var info = xdoc.Descendants("CstmrPmtStsRpt")
   .Descendants("OrgnlGrpInfAndSts")
   .Descendants("StsRsnInf")                                       
   .SelectMany(r=> r.Descendants("AddtlInf")).ToList();
   Console.WriteLine(info.Count); // prints 3.
Dotnet fiddle此处:

您可以在Linq中使用

var result = (string)xdoc.Descendants("member")
                         .FirstOrDefault(x => (string)x.Element("name") == "responseCode")
                         ?.Element("value");

    var info = xdoc.Descendants("CstmrPmtStsRpt")
   .Descendants("OrgnlGrpInfAndSts")
   .Descendants("StsRsnInf")                                       
   .SelectMany(r=> r.Descendants("AddtlInf")).ToList();
   Console.WriteLine(info.Count); // prints 3.

Dotnet fiddle这里:

作为一种选择,这对我来说似乎更容易:

var list = doc.XPathSelectElements
                ("Document/CstmrPmtStsRpt/OrgnlGrpInfAndSts/StsRsnInf/AddtlInf")
                .Select(n => n.Value);

作为一种选择,我觉得这更容易:

var list = doc.XPathSelectElements
                ("Document/CstmrPmtStsRpt/OrgnlGrpInfAndSts/StsRsnInf/AddtlInf")
                .Select(n => n.Value);

简单而有意义。简单而有意义。