XmlSerializer deserializing list with different element names

I am trying to parse XML that has an element that looks like the following using an XmlSerializer. There are quite a few currency types under the amount element and I'd like to deserialize them into a collection of objects that have a string property holding the currency type and an integer property holding the amount.

Is there any clean way of doing this without having to custom parse the amount. I'd like to just apply the XmlSerializer attributes to my classes and get something that works.

I have no control over the output XML.

<root>
 <property1>a</property1>
 <property1>b</property1>
 <property1>c</property1>
 <amount>
  <EUR type="integer">1000</EUR>
  <USD type="integer">1100</USD>
 </amount>
<root>

As I mentioned in a comment, the best way to attack XML deserialization is to start with serialization. To that end, here are some classes with attributes to control XML serialization:

public sealed class root
{
    [XmlElement("property1")]
    public List<string> property1;

    [XmlArrayItem(Type = typeof(EUR))]
    [XmlArrayItem(Type = typeof(USD))]
    public List<amount> amount;
}

public abstract class amount
{
    [XmlAttribute]
    public string type { get; set; }

    [XmlText]
    public string Value { get; set; }
}

public sealed class EUR : amount { }
public sealed class USD : amount { }

Test code is:

        var root = new root { property1 = new List<string>(), amount = new List<amount>() };
        root.property1.AddRange(new[]{ "a", "b", "c"});
        var eur = new EUR { type = "integer", Value = "1000" };
        var usd = new USD { type = "integer", Value = "1100" };
        root.amount.AddRange(new amount[]{ eur, usd});

which generates the following XML:

<?xml version="1.0" encoding="utf-16"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <property1>a</property1>
  <property1>b</property1>
  <property1>c</property1>
  <amount>
    <EUR type="integer">1000</EUR>
    <USD type="integer">1100</USD>
  </amount>
</root>

I think your best bet will be to do partial XML parsing, and keep the content of the <amount> element as a collection of XmlElement s. You'll still have to parse it manually, but you'll only have to parse that part manually. Example:

[XmlRoot("root")]
public class RecordInfo
{
    [XmlElement("property1")]
    public List<string> Property1;

    [XmlElement("amount")]
    public AmountRawData AmountData;
}

public class AmountRawData
{
    [XmlAnyElement]
    public List<XmlElement> Content;

    public IEnumerable<AmountInfo> Parse()
    {
        foreach (var element in this.Content)
        {
            yield return
                new AmountInfo()
                {
                    Currency = element.LocalName,
                    Type = element.GetAttribute("type"),
                    Amount = element.InnerText,
                };
        }
    }
}

public class AmountInfo
{
    public string Currency;
    public string Type;
    public string Amount;
}

Example usage:

var serializer = new XmlSerializer(typeof(RecordInfo));

var result = (RecordInfo)serializer.Deserialize(dataStream);

foreach (var amount in result.AmountData.Parse())
    Console.WriteLine($"{amount.Currency} {amount.Type} {amount.Amount}");

上周使用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:temptest.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            var results = doc.Elements().Select(x => new {
                property1 = x.Elements("property1").Select(y => (string)y).ToList(),
                dictCurrency = x.Elements("amount").Elements().GroupBy(y => y.Name.LocalName, z => (int)z)
                   .ToDictionary(y => y.Key, z => z.FirstOrDefault())
            }).FirstOrDefault();

        }
    }
}
链接地址: http://www.djcxy.com/p/54908.html

上一篇: 存储来自Git存储库的文件?

下一篇: XmlSerializer反序列化具有不同元素名称的列表