通过带有嵌套列表的LINQ从XML到类

时间:2019-02-25 22:19:21

标签: c# xml linq

因此,我尝试使用linq将以下xml代码解析为类,并且很难获取内部列表。 xml包含在我正在解析的XDocument中。

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

这是我正在使用的课程。

   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; }
}

如果此XML文档中没有内部列表,那将很简单,我可以做一个简单的LINQ查询即可。我不确定是否可以遍历内部列表。

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

有三个问题

  1. 串行器区分大小写。由于类名和xml标记名的大小写不匹配,因此需要在类的属性上方的方括号中添加属性
  2. 在阵列中进行序列化时,可以执行以下两项操作之一。首先,您可以为xml中的每个标签创建一个类。或者,您可以使用XmlArray和XmlArrayItem将两个标签合并为一个类。当每个xml标记都有一个类时,请使用XmlElement以及List对象或数组对象。如果没有XmlElement,则网络库将假定两个类(XmlArray和XmlArrayItem)。
  3. 您缺少xml文件中前两个标签的两个类。

请参见下面的代码

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; }
    }
}

添加了班级用户


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; }
    }
}

答案 1 :(得分:0)

以下是一些可以使用的功能。使用ClassinstanceFromXML从最里面构建它,它将完成:

    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();
    }

答案 2 :(得分:0)

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);
    }
 }

使用通用方法,您可以写入或读取包含列表的对象。

示例:

        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");