【问题标题】:Parse xml using LINQ to XML to class objects使用 LINQ to XML 解析 xml 以对对象进行分类
【发布时间】:2011-12-07 14:48:31
【问题描述】:

我有

<Model>
    <Components>
        <Component name="a" id="aaa" molarmass="60.05"/>
        <Component name="b" id="bbb" molarmass="18.02"/>
        <Component name="c" id="ccc" molarmass="32.04"/>
        <Component name="d" id="ddd" molarmass="46.03"/>
    </Components>
    ...
</Model>

和班级

public class ChemieComponent
{
    public string Name { get; set; }
    public string Id { get; set; }
    public double MolarMass { get; set; }
}

我可以使用 LINQ 查询将此组件解析为对象吗?如何?我到底应该有一个IEnumerable吧?

编辑

<Points>
    <Point name="P1" pressure="1">
    <Fractions>
        <Fraction id="aaa" value="0.15272159"/>
        <Fraction id="bbb" value="0.15272159"/>
    </Fractions>
    more points...
 </Points>

【问题讨论】:

    标签: c# linq-to-xml


    【解决方案1】:

    您可以使用以下内容:

    XDocument doc = XDocument.Parse(xml);
    IEnumerable<ChemieComponent> result = from c in doc.Descendants("Component")
                                          select new ChemieComponent()
                                          {
                                              Name = (string)c.Attribute("name"),
                                              Id = (string)c.Attribute("id"),
                                              MolarMass = (double)c.Attribute("molarmass")
                                          };
    

    编辑

    也可以使用 Linq to Xml 访问嵌套元素:

    public class Point 
    {
        public string Name { get; set; }
        public int Pressure { get; set; }
    
        public IEnumerable<Fraction> Fractions { get; set; }
    }
    
    public class Fraction
    {
        public string Id { get; set; }
        public double Value { get; set; }
    }
    
    static void Main()
    {
        string xml = @"<Points>
            <Point name='P1' pressure='1'>
                <Fractions>
                    <Fraction id='aaa' value='0.15272159'/>
                    <Fraction id='bbb' value='0.15272159'/>
                </Fractions>
            </Point>
            </Points>";
    
        XDocument doc = XDocument.Parse(xml);
        IEnumerable<Point> result = from c in doc.Descendants("Point")
                                    select new Point()
                                    {
                                        Name = (string)c.Attribute("name"),
                                        Pressure = (int)c.Attribute("pressure"),
                                        Fractions = from f in c.Descendants("Fraction")
                                                    select new Fraction() 
                                                    {
                                                        Id = (string)f.Attribute("id"),
                                                        Value = (double)f.Attribute("value"),
                                                    }
                                    };
    }
    

    【讨论】:

    • 可能要检查 null 否则您的应用程序将爆炸。
    • @Wouter:谢谢!这很好用。我可以进行子查询吗?还是必须进行两次查询?请查看我的编辑
    【解决方案2】:

    我意识到这是一篇旧文章,但我最近一直在做一些将 XML 读入对象的工作。我并不热衷于 Linq to XML - 它的可读性不强,依赖于“魔术字符串”,并且如果 XML 架构发生更改,则需要更改代码。

    对于任何感兴趣的人,我使用XmlSerializer 类将 XML 反序列化为对象。将反序列化代码放入通用辅助方法中,然后瞧 - 将 XML 文件反序列化为对象图的一行代码:-

    using System.IO;
    using System.Xml.Serialization;
    
    class Program
    {
        static void Main(string[] args)
        {
            var xml = @"<?xml version='1.0' encoding='utf-8' ?>
                <Model>
                    <Points>
                        <Point name='P1' pressure='1'>
                            <Fractions>
                                <Fraction id='aaa' value='0.15272159'/>
                                <Fraction id='bbb' value='0.15272159'/>
                            </Fractions>
                        </Point>
                    </Points>
                </Model>";
    
            var model = DeserializeObject<Model>(xml);
        }
    
        private static T DeserializeObject<T>(string xml)
        {
            var serializer = new XmlSerializer(typeof(T));
            using (var tr = new StringReader(xml))
            {
                return (T)serializer.Deserialize(tr);
            }
        }
    }
    
    public class Model
    {
        [XmlArrayItem("Point")]
        public Point[] Points { get; set; }
    }
    
    public class Point
    {
        [XmlAttribute(AttributeName = "name")]
        public string Name { get; set; }
    
        [XmlAttribute(AttributeName = "pressure")]
        public int Pressure { get; set; }
    
        [XmlArrayItem("Fraction")]
        public Fraction[] Fractions { get; set; }
    }
    
    public class Fraction
    {
        [XmlAttribute(AttributeName = "id")]
        public string Id { get; set; }
    
        [XmlAttribute(AttributeName = "value")]
        public double Value { get; set; }
    }
    

    几个注意事项:-

    这个解决方案显然依赖于用 XML 属性装饰域模型,这可能会或可能不会被您接受。该解决方案还依赖于 XML 中存在的外部元素,如果根元素是数组(本例中为 &lt;Points&gt;),则该解决方案将不起作用。

    无法指定IEnumerable&lt;&gt;(OP 提到的);你可以使用数组或List&lt;&gt;

    【讨论】:

    • 晚了 7 年,但 requires code changes if the XML schema changes 也适用于这个解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-08
    • 2012-02-16
    相关资源
    最近更新 更多