将 xml 个嵌套项转换为 C# 模型

convert xml nested items to c# model

我有 xml 这样的 :

<Root>
 <Products> 
    <Product>
      <ProductCode>1</ProductCode>
      <Properties no="45">
        <ColorProperties>
           <Color>Blue</Color>
        </ColorProperties>
      </Properties>
    </Product>
    <Product>
      <ProductCode>2</ProductCode>
      <Properties no="45">
        <ColorProperties>
           <Color>Red</Color>
        </ColorProperties>
      </Properties>
    </Product>
     <Product>
      <ProductCode>3</ProductCode>
      <Properties no="45">
        <ColorProperties>
           <Color>Yellow</Color>
        </ColorProperties>
      </Properties>
    </Product>
 </Products>
</Root>

我想转换为产品模型,

class Product 
{
//must be filled
}

产品顶部必须有我的属性 class 说产品属于产品,产品属于根。

我该怎么做?

我的英语不是很好很抱歉:)。

所以我不想创建 Root 和 Products 类(我认为必须有多个 [XmlRoot]),我想用 [XmlArray] 和 [XmlArrayItem] 装饰属性(及其嵌套属性)但我做不到。

如何使用 c# 将此 xml 转换为产品 class?

您可以使用 Visual Studio 的特殊粘贴魔法(编辑 - 特殊粘贴 - 粘贴为 XML)class 将任何实体搭建到 POCO class

我正是这样做的,以使用您的 XML 文件生成您的实体 classes。

现在,假设我们有以下实体 classes :

using System;
using System.ComponentModel;
using System.Xml.Serialization;

namespace XmlToClass
{

[Serializable()]
[DesignerCategory("code")]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public partial class Root
{

    private RootProduct[] productsField;

    [XmlArrayItem("Product", IsNullable = false)]
    public RootProduct[] Products
    {
        get
        {
            return this.productsField;
        }
        set
        {
            this.productsField = value;
        }
    }
}


[Serializable()]
[DesignerCategory("code")]
[XmlType(AnonymousType = true)]
public partial class RootProduct
{

    private byte productCodeField;

    private RootProductProperties propertiesField;

    public byte ProductCode
    {
        get
        {
            return this.productCodeField;
        }
        set
        {
            this.productCodeField = value;
        }
    }

    public RootProductProperties Properties
    {
        get
        {
            return this.propertiesField;
        }
        set
        {
            this.propertiesField = value;
        }
    }
}

[Serializable()]
[DesignerCategory("code")]
[XmlType(AnonymousType = true)]
public partial class RootProductProperties
{

    private RootProductPropertiesColorProperties colorPropertiesField;

    private byte noField;

    public RootProductPropertiesColorProperties ColorProperties
    {
        get
        {
            return this.colorPropertiesField;
        }
        set
        {
            this.colorPropertiesField = value;
        }
    }

    [XmlAttribute()]
    public byte no
    {
        get
        {
            return this.noField;
        }
        set
        {
            this.noField = value;
        }
    }
}


[Serializable()]
[DesignerCategory("code")]
[XmlType(AnonymousType = true)]
public partial class RootProductPropertiesColorProperties
{

    private string colorField;

    /// <remarks/>
    public string Color
    {
        get
        {
            return this.colorField;
        }
        set
        {
            this.colorField = value;
        }
    }
}

}

只需使用通用方法添加此助手 class :

    public class XmlToEntity
{
    public T FromXml<T>(String xml)
    {
        T returnedXmlClass = default(T);

        try
        {
            using (TextReader reader = new StringReader(xml))
            {
                try
                {
                    returnedXmlClass =
                        (T)new XmlSerializer(typeof(T)).Deserialize(reader);
                }
                catch (InvalidOperationException)
                {
                    // String passed is not XML, simply return defaultXmlClass
                }
            }
        }
        catch (Exception ex)
        {
        }

        return returnedXmlClass;
    }
}

然后在您的控制台中尝试此操作:

        static void Main(string[] args)
    {
        var conv = new XmlToEntity();
        Root root = conv.FromXml<Root>(File.ReadAllText("data.xml"));
        Console.WriteLine(root.Products.Length.ToString());
    }

注:

如果您希望使用不同的查询,您可以使用匿名类型和一点 LINQ,如下所示:

        var query = root.Products.Select(x => new
        {
            ProductCode = x.ProductCode,
            ProductColor = x.Properties.ColorProperties.Color,
        });

您可以尝试 Cinchoo ETL - 一个开源库,以简化的方式反序列化 xml 中的选定节点。

首先用 xpath 定义 POCO class 以从产品节点中提取子节点

public class Product
{
    public int ProductCode { get; set; }
    [ChoXPath("Properties/@no")]
    public int PropertyNo { get; set; }
    [ChoXPath("Properties/ColorProperties/Color")]
    public string Color { get; set; }
}

然后使用 ChoXmlReader 从 xml 加载产品节点,如下所示

using (var r = ChoXmlReader<Product>.LoadText(xml)
       .WithXPath("//Product")
      )
{
    r.Print();
}

输出:

-- Program+Product State -- 
    ProductCode: 1
    PropertyNo: 45
    Color: Blue


-- Program+Product State -- 
    ProductCode: 2
    PropertyNo: 45
    Color: Red


-- Program+Product State -- 
    ProductCode: 3
    PropertyNo: 45
    Color: Yellow

示例 fiddle:https://dotnetfiddle.net/uBzXpt