如何反序列化元素名称列表编号的XML?

问题描述:

大家好消息! 我遇到了一些棘手的XML新问题。如何反序列化元素名称列表编号的XML?

<?xml version="1.0" encoding="UTF-8"?> 
<response> 
<osmp_txn_id>100500</osmp_txn_id> 
<result>0</result> 
<fields> 
<field1 name="name">Ko Chu Bey</field1> 
<field2 name="contract">777-1</field2> 
... 
<fieldN name="account">65000</fieldN> 
</fields> 
<comment>Result for round 1 of fight vs Pe Re Svet: 1:1</comment> 
</response> 

我的问题是,内置的实用工具,生成XSD的ANS CS的使不同类各fieldX。而且因为它们的数量可能会很多,所以它变成了一个非常亲密的地方。 有没有办法将对象从这个XML反序列化成一个具有field对象数组的类?

+0

您需要完全控制反序列化过程;看起来像这些字段可以创建一个不错的KeyValuePair。在我的手机上,现在无法真正给出答案,但我会研究如何实现ISerializable。 – 2013-04-09 12:09:03

如果你有一个字符串,你可以做到这一点使用LINQ to XML和名称的正则表达式的XML:

var fieldElementNameRegex = new Regex(
    "^field[0-9]+$", 
    RegexOptions.IgnoreCase | RegexOptions.Compiled); 

var xml = XElement.Parse(xmlString); 

var fieldElements = xml 
    .Descendants() 
    .Where(e => fieldElementNameRegex.IsMatch(e.Name.ToString())) 
    .ToArray(); 
+0

对不起,看起来像我所说的被误解了。我知道,是否有可能将这样的xml反序列化成一个具有'field'对象数组的类。 – Hikiko 2013-04-09 12:05:50

+0

作为一种可能的解决方案,我发现使用'Regex'遍历响应字符串并将所有'fieldX'变成'field'并在替换后将其反序列化。 – Hikiko 2013-04-09 12:08:37

+0

只是为了澄清你为什么指'反序列化' - 你的意思是在运行时将它变成一个对象? – 2013-04-09 12:10:17

最好的解决办法是让自己的IXmlSerializable实施使用XML有问题。预先做好会很麻烦,但从长远来看,这可能是值得的。

作为一种替代方法(我不会推荐它太强烈),您可以写一些小技巧来反思默认序列化对象的属性 - 您解释的属性是由内置实用程序生成的。

例如,假设:

公共类字段 { 公共字符串名称; 公共字符串值; }

public class response 
{ 
    public Field field1; 
    public Field field2; 
    public Field field3; 
    public Field field4; 
    public Field field5; 
    public Field field6; 
    public Field field7; 
    public string comments; 
    public string osmp_txn_id; 
    public string result; 
} 

可以定义下面的 “方便” 类:

public class myResponse 
{ 
    public string comments; 
    public string osmp_txn_id; 
    public string result; 
    public List<Field> fields; 
} 

,这将是如何填充更方便类:

myResponse ConvertFromResult(response target) 
{ 
    var returnObject = new myResponse(); 

    var fields = target.GetType().GetFields().Where(f => f.FieldType == typeof(Field)); 
    returnObject.fields = (from f in fields 
    let fp = f.GetValue(target) as Field 
    where fp != null 
    select fp).ToList(); 

    returnObject.comments = target.comments; 
    returnObject.osmp_txn_id = target.osmp_txn_id; 
    returnObject.result = target.result; 

    return returnObject; 
} 

这都是概念性的,所以你可能需要从这里“推出自己的”解决方案。另一种方法是使用扩展方法为xml反序列化对象返回一个IEnumerable<field>,如果要以非性能密集型方式使用它,这将是可行的。

public static class responseExtensions 
{ 
    private static IEnumerable<Field> GetFields(this response target) 
    { 
    var fields = target.GetType().GetFields().Where(f => f.FieldType == typeof(Field)); 
    return from f in fields 
      let fp = f.GetValue(target) as Field 
      where fp != null 
      select fp; 
    } 
}