0

New to linq and XML and looking for a way to return values of
<AddtlInf></AddtlInf> as a list which I will then concatenate the values to a single string.

XML below:

<?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>

So far I have:

var info = doc.Descendants(ns + "CstmrPmtStsRpt")
           .Descendants(ns + "OrgnlGrpInfAndSts")
           .Descendants(ns + "StsRsnInf")                                       
           .Select(r => new
           {
                Info = r.Element(ns + "AddtlInf").Value                                          
           }).ToList();

But this only returns "Duplicate File", the first value. How do I fix this?

4 Answers 4

2

You need to access the sub-elements of 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();

By using Element(without trailing s), you only access a single element instead of several, hence your result does only contain the value of the first element.

By using SelectMany as opposed to Select you can return several elements from sub-enumerations.

Sign up to request clarification or add additional context in comments.

1 Comment

Simple and makes sense.
0

In your code, r.Element will always return you the first element of the collection. Instead try to use r.Elements, which will return you the collection of "AddtlInf" elements.

For detailed information about this, have a look at this link!

Comments

0

You may use SelectMany in 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 here: https://dotnetfiddle.net/IKd7go

Comments

0

As an alternative this seems easier to me:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.