如何在不定义父节点的情况下反序列化 XML 文件?

How can I deserialize a XML file without defining the parent node?

我知道有很多关于xml文件反序列化的内容,但是我至今没有找到解决办法。我的 XML 看起来像这样

<Data>
    <Products>
        <Product name="product1" brand="brand1">
            <ProductValues>
                <ProductValue name="price" value="100"/> 
                <ProductValue name="stock" value="23"/>
            </ProductValues>
        </Product>
        <Product name="product2" brand="brand1">
            <ProductValues>
                <ProductValue name="price" value="100"/> 
                <ProductValue name="stock" value="23"/>
            </ProductValues>
        </Product>
        <Product name="product2" brand="brand1">
            <ProductValues>
                <ProductValue name="price" value="100"/> 
                <ProductValue name="stock" value="23"/>
            </ProductValues>
        </Product>
    </Products>

    ... <!-- And more products -->

</Data>

我有一个 Product 和 ProductValue class,其中相应的字段标记为 XmlAttribute

public class Product
{
    [XmlAttribute]
    public string name;
    [XmlAttribute]
    public string brand;
    public ProductValue[] ProductValues

    ... 
}

一切正常发现,如果我创建一个新的 class,它被称为 Data 并且有一个字段 public Product[] products 并且我像这样反序列化

XmlSerializer serializer = new XmlSerializer(typeof(Data));
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
    Data data = (Data)serializer.Deserialize(stream);
}

我不想为此创建一个额外的 class,也不想创建一个像 here 这样的额外字段,但只使用数组类型 XmlSerializer serializer = new XmlSerializer(typeof(Product[])); 实例化序列化程序以接收本地 Product[]。但是如果我这样做,我会得到错误 <Data xmlns="> was not expected

使用 Xml Linq:

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            List<Product> products = doc.Descendants("Product").Select(x => new Product() {
                name = (string)x.Attribute("name"),
                brand = (string)x.Attribute("brand"),
                ProductValues = x.Descendants("ProductValue")
                    .GroupBy(y => (string)y.Attribute("name"), z => (string)z.Attribute("value"))
                    .ToDictionary(y => y.Key, z => z.FirstOrDefault())
            }).ToList();

        }
    }
    public class Product
    {
        public string name { get; set; }
        public string brand { get; set; }
        public Dictionary<string, string> ProductValues { get; set; }
    }

}

正如@Rand Random 指出的可能的重复,我查看了那个问题,最后 git 它结合了 this and this.

XmlReader reader = XmlReader.Create(path);
reader.MoveToContent();
reader.ReadToDescendant("Products");
XmlSerializer serializer = new XmlSerializer(typeof(Product[]), new XmlRootAttribute() { ElementName = "Products" });

var products = (Product[])serializer.Deserialize(reader);