David Austin
David Austin

Reputation: 13

Reading a Childs child attribute with Linq

I have a xml doc

<CollRpt>
   <Sumry SumryID="0001">
      <BT BTID="1234" >
         <FT FTID="24240981145200123809844" >
          </FT>
         <AcctCls CrInd="1">
            <Ckey/>
         </AcctCls>
      </BT>
      <Vchr  VchrID="215"/>
      <Tot TotCnt="4"/>
   </Sumry>
</CollRpt>

I need to get several attributes from each "Sumry" element and child elements only if the Vchr element has a VchrID == 215. I have tried it several different ways but have had no luck. Any guidance would be greatly appreciated.

 var xml = XDocument.Load(@newFile);
            var query = (from c in xml.Root.Descendants("CollRpt")
                         let s = c.Descendants("Sumry")
                         let v = s.Elements("Vchr")
                         where v.Attributes("VchrFormCd").Equals("215")
                         select new { SumryID = s.Attributes("SumryID"), ALC = v.Attributes("VchrID") }).ToList();

           
            foreach (var q in query)
            {
                Console.WriteLine("{0}: {1}\n", q.SumryID ,q.VchrID);
            }

Upvotes: 1

Views: 57

Answers (1)

Trevor
Trevor

Reputation: 8004

I need to get several attributes from each "Sumry" element and child elements only if the Vchr element has a VchrID == 215. I have tried it several different ways but have had no luck. Any guidance would be greatly appreciated

I would recommend creating classes so you can deserialize this xml into classes that can be easily searchable, filtered etc. Please see these below.

[XmlRoot(ElementName = "FT")]
    public class FT
    {

        [XmlAttribute(AttributeName = "FTID")]
        public double FTID { get; set; }
    }

    [XmlRoot(ElementName = "AcctCls")]
    public class AcctCls
    {

        [XmlElement(ElementName = "Ckey")]
        public object Ckey { get; set; }

        [XmlAttribute(AttributeName = "CrInd")]
        public int CrInd { get; set; }
    }

    [XmlRoot(ElementName = "BT")]
    public class BT
    {

        [XmlElement(ElementName = "FT")]
        public FT FT { get; set; }

        [XmlElement(ElementName = "AcctCls")]
        public AcctCls AcctCls { get; set; }

        [XmlAttribute(AttributeName = "BTID")]
        public int BTID { get; set; }
    }

    [XmlRoot(ElementName = "Vchr")]
    public class Vchr
    {

        [XmlAttribute(AttributeName = "VchrID")]
        public int VchrID { get; set; }
    }

    [XmlRoot(ElementName = "Tot")]
    public class Tot
    {

        [XmlAttribute(AttributeName = "TotCnt")]
        public int TotCnt { get; set; }
    }

    [XmlRoot(ElementName = "Sumry")]
    public class Sumry
    {

        [XmlElement(ElementName = "BT")]
        public BT BT { get; set; }

        [XmlElement(ElementName = "Vchr")]
        public Vchr Vchr { get; set; }

        [XmlElement(ElementName = "Tot")]
        public Tot Tot { get; set; }

        [XmlAttribute(AttributeName = "SumryID")]
        public int SumryID { get; set; }
    }

    [XmlRoot(ElementName = "CollRpt")]
    public class CollRpt
    {

        [XmlElement(ElementName = "Sumry")]
        public List<Sumry> Sumry { get; set; }
    }

Now you can deserialize this xml by doing:

using (var fileStream = new FileStream("YOURXMLPATH", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            using (StreamReader reader = new StreamReader(fileStream))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(CollRpt));
                var test = (CollRpt)serializer.Deserialize(reader);

                var found = test.Sumry.Where(s => s.Vchr.VchrID == 215).ToList();
            }
        }

In the above, test would be the CollRpt class with all the data you would need. In the found, it would contain a List<Sumry> of the data that you filtered based on your condition.

Upvotes: 1

Related Questions