XML to Classes via LINQ with nested lists

linq select nested list
linq query for nested list in c
c# linq select list within list
linq select new nested list
c# linq select from list of objects
nested linq queries example c#
c find object in nested list
linq selectmany

So I am trying to parse out this xml code below using linq into classes and I am having a hard time getting the inner lists. The xml is contained in an XDocument that I am parsing through.

<Response>
<ResponseTransaction>
    <transaction>
        <tranId>3216</tranId>
        <tranName>TestTran01</tranName>
        <tranResultList>
            <tranResult>
                <state>Expired</state>
                <created>2019-02-23</created>
                <docList>
                    <doc id="1" name="Doc1" />
                    <doc id="2" name="Doc2" />
                    <doc id="3" name="Doc3" />
                    <doc id="4" name="Doc4" />
                </docList>
                <roleList>
                    <role role="usrRole" id="1">
                        <firstName>Jack</firstName>
                        <lastName>Daniels</lastName>
                        <email>jd@gmail.com</email>
                        <docList>
                            <doc id="1" name="Doc1" status="removed" />
                            <doc id="2" name="Doc2" status="current" />
                            <doc id="3" name="Doc3" status="current" />
                            <doc id="4" name="Doc4" status="current" />
                        </docList>
                    </role>
                </roleList>
            </tranResult>
            <tranResult>
                <state>undefined</state>
                <created>2019-02-24</created>
                <docList>
                    <doc id="1" name="Doc1" />
                    <doc id="2" name="Doc2" />
                    <doc id="3" name="Doc3" />
                    <doc id="4" name="Doc4" />
                </docList>
                <roleList>
                    <role role="usrRole" id="1">
                        <firstName>Jack</firstName>
                        <lastName>Daniels</lastName>
                        <email>jd@gmail.com</email>
                        <docList>
                            <doc id="1" name="Doc1" status="removed" />
                            <doc id="2" name="Doc2" status="current" />
                            <doc id="3" name="Doc3" status="current" />
                            <doc id="4" name="Doc4" status="current" />
                        </docList>
                    </role>
                </roleList>
            </tranResult>
            <tranResult>
                <state>Current</state>
                <created>2019-02-25</created>
                <docList>
                    <doc id="1" name="Doc1" />
                    <doc id="2" name="Doc2" />
                    <doc id="3" name="Doc3" />
                    <doc id="4" name="Doc4" />
                </docList>
                <roleList>
                    <role role="usrRole" id="1">
                        <firstName>Jack</firstName>
                        <lastName>Daniels</lastName>
                        <email>jd@gmail.com</email>
                        <docList>
                            <doc id="1" name="Doc1" status="removed" />
                            <doc id="2" name="Doc2" status="current" />
                            <doc id="3" name="Doc3" status="current" />
                            <doc id="4" name="Doc4" status="current" />
                        </docList>
                    </role>
                </roleList>
            </tranResult>
        </tranResultList>
     </transaction>
   </ResponseTransaction>
</Response>

Here are the classes I am working with.

   public class Transaction {
        public string TranId { get; set; }
        public string TranName { get; set; }
        public List<TranResult> TranResultList { get; set; }
}

public class TranResult {
        public string State { get; set; }
        public string DateCreated { get; set; }
        public List<Document> DocumentList { get; set; }
        public List<Role> RoleList { get; set; }
}

public class Document {
        public string Id { get; set; }
        public string Name { get; set; }
        public string status { get; set; }
}

public class Role {
        public string Id { get; set; }
        public string RoleName { get; set; }
        public User user { get; set; }
}

public class User {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public List<Document> DocumentList { get; set; }
}

If there were no inner lists in this XML document then it would be simple and I could do just a simple LINQ query and be done. I am not sure I I can loop through the inner lists through.

Any help is appreciated.

There were three issues

  1. The serializer is case sensitive. Since the capitialization of your class names and the xml tag names didn't match you need to add attributes in square brackets above the properties in the classes
  2. When you have arrays in serialization you can do one of two things. First you can have a class for each tag in the xml. Or you can combine two tags into one class using XmlArray and XmlArrayItem. When having a class for each xml tag use XmlElement along with a List object or an array object. Without XmlElement the Net Library assumes two classes (XmlArray and XmlArrayItem).
  3. You were missing two classes for the first two tags in the xml file.

See code below

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(Response));
            Response response = (Response)serializer.Deserialize(reader);

        }
    }
    [XmlRoot("Response")]
    public class Response
    {
        [XmlElement("ResponseTransaction")]
        public ResponseTransaction responseTransaction { get; set; }
    }
    [XmlRoot("ResponseTransaction")]
    public class ResponseTransaction
    {
        [XmlElement("transaction")]
        public Transaction transaction { get; set; }
    }
    [XmlRoot("transaction")]
    public class Transaction
    {
        [XmlElement("tranId")]
        public string TranId { get; set; }
        [XmlElement("tranName")]
        public string TranName { get; set; }
        [XmlArray("tranResultList")]
        [XmlArrayItem("tranResult")]
        public List<TranResult> TranResultList { get; set; }
    }

    public class TranResult
    {
        [XmlElement("state")]
        public string State { get; set; }
        [XmlElement("created")]
        public string DateCreated { get; set; }
        [XmlArray("docList")]
        [XmlArrayItem("doc")]
        public List<Document> DocumentList { get; set; }
        [XmlArray("roleList")]
        [XmlArrayItem("role")]
        public List<Role> RoleList { get; set; }
    }

    public class Document
    {
        [XmlAttribute("id")]
        public string Id { get; set; }
        [XmlAttribute("name")]
        public string Name { get; set; }
        [XmlAttribute("status")]
        public string status { get; set; }
    }

    public class Role
    {
        [XmlAttribute("id")]
        public string Id { get; set; }
        [XmlAttribute("role")]
        public string RoleName { get; set; }
        [XmlElement("firstName")]
        public string FirstName { get; set; }
        [XmlElement("lastName")]
        public string LastName { get; set; }
        [XmlElement("email")]
        public string Email { get; set; }
        [XmlArray("docList")]
        [XmlArrayItem("doc")]
        public List<Document> DocumentList { get; set; }
    }
}

Added a Class User


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(Response));
            Response response = (Response)serializer.Deserialize(reader);

        }
    }
    [XmlRoot("Response")]
    public class Response
    {
        [XmlElement("ResponseTransaction")]
        public ResponseTransaction responseTransaction { get; set; }
    }
    [XmlRoot("ResponseTransaction")]
    public class ResponseTransaction
    {
        [XmlElement("transaction")]
        public Transaction transaction { get; set; }
    }
    [XmlRoot("transaction")]
    public class Transaction
    {
        [XmlElement("tranId")]
        public string TranId { get; set; }
        [XmlElement("tranName")]
        public string TranName { get; set; }
        [XmlArray("tranResultList")]
        [XmlArrayItem("tranResult")]
        public List<TranResult> TranResultList { get; set; }
    }

    public class TranResult
    {
        [XmlElement("state")]
        public string State { get; set; }
        [XmlElement("created")]
        public string DateCreated { get; set; }
        [XmlArray("docList")]
        [XmlArrayItem("doc")]
        public List<Document> DocumentList { get; set; }
        [XmlArray("roleList")]
        [XmlArrayItem("role")]
        public List<Role> RoleList { get; set; }
    }

    public class Document
    {
        [XmlAttribute("id")]
        public string Id { get; set; }
        [XmlAttribute("name")]
        public string Name { get; set; }
        [XmlAttribute("status")]
        public string status { get; set; }
    }

    public class Role
    {
        private User user = new User();
        [XmlAttribute("id")]
        public string Id { get; set; }
        [XmlAttribute("role")]
        public string RoleName { get; set; }

        [XmlElement("firstName")]
        public string FirstName {
            get { return user.FirstName; }
            set { user.FirstName = value; }
        }

        [XmlElement("lastName")]
        public string LastName
        {
            get { return user.LastName; }
            set { user.LastName = value; }
        }

        [XmlElement("email")]
        public string Email
        {
            get { return user.Email; }
            set { user.Email = value; }
        }

        [XmlArray("docList")]
        [XmlArrayItem("doc")]
        public List<Document> DocumentList {
            get { return user.DocumentList; }
            set { user.DocumentList = value; } 
        }

    }
    public class User
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public List<Document> DocumentList { get; set; }
    }
}

[Solved] Nested list how extract using linq, Ignoring that your sample code won't compile - always check your code works and produces the problem in simplified form or we all waste a� First you can have a class for each tag in the xml. Or you can combine two tags into one class using XmlArray and XmlArrayItem. When having a class for each xml tag use XmlElement along with a List object or an array object. Without XmlElement the Net Library assumes two classes (XmlArray and XmlArrayItem).

Here are some functions that can be used. Build it up from the innermost with a ClassinstanceFromXML, and it will be completed :

    public static XElement GetTransaction(XDocument xDoc)
    {
        return xDoc.Descendants("transaction").FirstOrDefault();
    }

    public static Transaction TransactionFromXML(XElement transactionXElement)
    {
        string tranId = transactionXElement.Element("tranId").Value;
        string tranName = transactionXElement.Element("tranName").Value;
        //transform all <tranResult> Xelements into Class objects
        //by passing the xml content of those tags into the TransResultFromXML selector function
        List<TranResult> transResults = transactionXElement.Element("tranResultList")?
            .Elements("tranResult")?.Select(TransResultFromXML).ToList();

        Transaction t = new Transaction()
        {
            TranId = tranId,
            TranName = tranName,
            TranResultList = transResults
        };
        return t;
    }

    public static TranResult TransResultFromXML(XElement transResultElement)
    {
        string state = transResultElement.Element("state").Value;
        string dateCreated = transResultElement.Element("created").Value;
        List<Document> docList;
        //transform all <doc> Xelements in <docList> into Class objects
        //by passing the xml content of those tags into the DocumentFromXML selector function
        docList = transResultElement.Element("docList")?
            .Elements("doc")?.Select(DocumentFromXML).ToList();
        List<Role> roleList;

        //transform all <role> Xelements in <roleList> into Class objects
        //by passing the xml content of those tags into the RoleFromXML selector function
        roleList = transResultElement.Element("roleList")?
            .Elements("role")?.Select(RoleFromXML).ToList();

        return new TranResult()
        {
            State = state,
            DateCreated = dateCreated,
            DocumentList = docList,
            RoleList = roleList
        };
    }

    public static Role RoleFromXML(XElement roleElement)
    {
        string id = roleElement.Attribute("id").Value;
        string roleName = roleElement.Attribute("role").Value;
        //A similar apttern has been used above - do same here
        List<Document> userDocList = roleElement.Element("docList")?
            .Elements("doc")?.Select(DocumentFromXML).ToList();
        User myUser = new User()
        {
            FirstName = roleElement.Element("firstName")?.Value,
            LastName = roleElement.Element("lastName")?.Value,
            Email = roleElement.Element("email")?.Value,
            DocumentList = userDocList
        };
        return new Role()
        {
            Id = id,
            RoleName = roleName,
            user = myUser
        };
    }

    public static Document DocumentFromXML(XElement docElement)
    {
        return new Document()
        {
            Id = docElement.Attribute("id").Value,
            Name = docElement.Attribute("name").Value,
            status = docElement.Attribute("status")?.Value
        };
    }

    static void Main(string[] args)
    {
        XDocument x = XDocument.Load(@"Path\To\transactions.xml");
        Transaction myTransaction = TransactionFromXML(GetTransaction(x));

        Console.WriteLine(myTransaction.TranResultList.ElementAt(1).RoleList.ElementAt(0).user.Email);

        Console.ReadLine();
    }

Nested List selection, public partial class User { public string UserName{ get; set; } public I need to read this xml using linq to xml concept. i have tried ling to xml ways and getting null values when getting the family. basically struggling to get nested list so that we can try to find a way to add a null value in the node if value is� Hello, I was some nested list, and I would like to extract complexe information, but I don't know how write the linq expression. public class Section { public List<Side> SideList {get; set; } = new List<Side>() } public class Side { public List<PositionSide> PositionList {get; set; } = new List<PositionSide>() } public class PositionSide : { public int Position {get; set;} .

public static class MyMethods
{       
    public static void XMLWrite<T>(this T obj, string PathXML) where T : class, new()
    {

            if (Directory.Exists(Path.GetDirectoryName(PathXML)))
            {
                using (FileStream stream = new FileStream(PathXML, FileMode.Create))
                using (XmlTextWriter writer = new XmlTextWriter(stream, Encoding.Unicode))
                {
                    XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());
                    xmlSerializer.Serialize(writer, obj);
                }
            }
    }

    public static T XMLRead<T>(this string PathXML) where T : class, new()
    {
            if (File.Exists(PathXML))
            {
                XmlSerializer xmlOkuyucu = new XmlSerializer(typeof(T));
                using (Stream okuyucu = new FileStream((PathXML), FileMode.Open))
                {
                    return (T)xmlOkuyucu.Deserialize(okuyucu);
                }
            }
            return default(T);
    }
 }

With generic method you can write or read your object which includes list.

Examples :

        object1 = MyMethods.XMLRead<YourClass>(string.Format("{0}\\{1}", locationXML, "file1.xml"));
        object2 = MyMethods.XMLRead<List<YourClass2>>(string.Format("{0}\\{1}", locationXML, "file2.xml"));

        object3.XMLWrite(Path.GetDirectoryName(Application.ExecutablePath) + "\\file3.xml");

Creating a Nested List from a Flat List in C#, linq query for nested list in c# I currently have the following classes: public class NavigationItem { public int ID { get; set; } public string Title { get; set; } public int� Creating class objects using LINQ with a highly nested XML Tag: c# , xml , wpf , linq I have xml files that I need to load and create class objects from, however, these files are formatted in, what seems to me to be a ridiculously nested way.

Linq to filter nested list, linq query for nested list in c# c# filter how to filter two list in c# using linq c# linq class EntityName { int i; string xx; List<SubEntity> subEntityName; }. Then� Just change the conditions that you are querying on. I'm converting your FindAll to a Where clause as I know that works for nested queries. I'm also converting this to a method, since as a property the possibility exists that ddlCertificate has a null value, which will cause an exception if the property is called prematurely.

C# Language, if you want to output all permutations you could use nested loops like var result = new List<string>(); foreach (var s1 in list1) foreach (var s2 in list2) result. Using the two LINQ methods, this can be implemented as follows. var result = first .Zip(second, (f, s) => new Type[] {a, b}) .SelectMany(x => x); As you can see, we first use Zip to take one element from each of the lists, and combine them into a small array of two elements, and then flatten all those arrays using SelectMany .

Creating XML Trees in C# (LINQ to XML), Learn about creating XML trees in C#, including constructing The XElement class uses the following constructors for functional The attributes and/or child elements are created from the contents of the parameter list. For information about using the results of LINQ queries as the content for an XElement, see Functional Construction (LINQ to XML) (C#). Constructing elements The signatures of the XElement and XAttribute constructors let you pass the contents of the element or attribute as arguments to the constructor.

Comments
  • You've given a nice example of the XML and the C# classes, but not really showed where your parsing code is. It is no problem to get XML snippets out - those should represent enough data to instantiate your objects. What is the real stumbling block?
  • Thank you! This approach makes more sense in my application as it allows me to just deserialize the xml into my classes which is "more readable" then trying to parse the query using LINQ.
  • Upvoted because this showed me the way with attributes and just deserialising. Nice explanation too!
  • I did notice that User class was dropped - is that a design choice , or is it impossible to get it from the original OP XML? I couldn't get it to work.
  • I initially just followed the xml file. Then after I posted early this morning I said you might ask what happened to the User Class so I figured a way of doing it. Then you asked the question. So I added a 2nd solution with a class for User.