2017-01-23 119 views
1

我想解析具有使用XmlSerializer类似于下面的元素的XML。 amount元素下有不少货币类型,我想将它们反序列化为一个对象的集合,这些对象具有一个保存货币类型的字符串属性和一个保存金额的整数属性。带有不同元素名称的XmlSerializer反序列化列表

是否有任何干净的方式做到这一点,而不必自定义分析数量。我想只将XmlSerializer属性应用于我的类并获得一些有用的东西。

我无法控制输出XML。

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

攻击XML序列化的最佳方式是*序列化*生成所需的XML。 –

回答

0

回答类似的问题,上周我在留言中提到,攻击XML序列化的最佳方式是从序列化开始。为此,这里有一些类与属性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 { } 

测试代码:

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

产生以下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> 
+0

我认为这是我所要求的最接近的,尽管我不喜欢每种货币都有类别。另外我不确定是否有更好的方法,但是我使用反射来获取货币名称,并在返回GetType()。Name的抽象类上使用属性。 – DSteveson

0

我觉得你最好的选择将是做局部的XML解析,并保持<amount>元素的含量为XmlElement个集合。你仍然需要手动解析它,但是你只需要手动解析那部分。例如:

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

用法示例:

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

使用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); 

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

     } 
    } 
} 
相关问题