反序列化具有多种类型的XML [英] Deserialize XML with multiple types

查看:78
本文介绍了反序列化具有多种类型的XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试反序列化某些相同名称标签具有不同xsi类型的XML:

I'm trying to deserialize XML where some same name tags have different xsi types:

<user-defined-data-row>
  <field name="entity">
    <field-value xsi:type="field-text-valueType">
      <value>Test</value>
    </field-value>
  </field>
  <field name="expiry_date">
    <field-value xsi:type="field-date-valueType">
      <value>2001-10-07</value>
    </field-value>
  </field>
</user-defined-data-row>

这很容易通过将xml反序列化到此模型中来实现:

This is easily achieved by deserializing the xml into this model:

[XmlRoot(ElementName = "field-value", Namespace = "http://www.crsoftwareinc.com/xml/ns/titanium/common/v1_0")]
[XmlType("field-text-valueType")]
public class Fieldvalue
{
    [XmlElement(ElementName = "value", Namespace = "http://www.crsoftwareinc.com/xml/ns/titanium/common/v1_0")]
    public string Value { get; set; }
}

唯一不同的是XML中的类型:

The only thing that differs are the types in the XML:

field-text-valueType

field-date-valueType

我如何使用类似的方法使C#类解释两种类型?

How can I make the C# class interpret both types using something like

[XmlType("field-text-valueType")]

反序列化不序列化

推荐答案

在XML中看到的 xsi:type 属性是标准的W3C XML Schema属性,该属性允许元素显式指定其类型.;有关详细信息,请参见此处.如 Xsi​​:type属性绑定支持 XmlSerializer 支持这种用于多态类型反序列化的机制,特别是通过使用

The xsi:type attributes you are seeing in your XML are standard W3C XML Schema attributes that allow an element to explicitly specify its type; for details see here. As explained in Xsi:type Attribute Binding Support, XmlSerializer supports this mechanism for deserialization of polymorphic types, specifically by use of XmlIncludeAttribute.

首先,如下定义一个抽象基类 FieldValue :

First, define an abstract base class FieldValue as follows:

public static class XmlNamespaces
{
    public const string Crsoftwareinc = "http://www.crsoftwareinc.com/xml/ns/titanium/common/v1_0";
}

[XmlRoot("field-value", Namespace = XmlNamespaces.Crsoftwareinc)]
[XmlType("field-value", Namespace = XmlNamespaces.Crsoftwareinc)]
[XmlInclude(typeof(TextFieldValue)), 
XmlInclude(typeof(DateFieldValue))]
public abstract partial class FieldValue
{
    // It's not necessary to have this in the base class but I usually find it convenient.
    public abstract object GetValue();
}

接下来,为每个可能的 xsi:type ="XXX" 值定义 FieldValue 的派生类型,其

Next, for each possible xsi:type="XXX" value, define a derived type of FieldValue whose XmlTypeAttribute.TypeName matches the xsi:type value. Decorate the base class with [XmlInclude(typeof(TDerivedFieldValue))] attributes for each (already shown above):

[XmlRoot("field-text-valueType", Namespace = XmlNamespaces.Crsoftwareinc)]
[XmlType("field-text-valueType", Namespace = XmlNamespaces.Crsoftwareinc)]
public class TextFieldValue : FieldValue
{
    [XmlElement("value")]
    public string Value { get; set; }

    public override object GetValue() { return Value; }
}

[XmlRoot("field-date-valueType", Namespace = XmlNamespaces.Crsoftwareinc)]
[XmlType("field-date-valueType", Namespace = XmlNamespaces.Crsoftwareinc)]
public class DateFieldValue : FieldValue
{
    [XmlElement("value", DataType = "date")]
    public DateTime Value { get; set; }

    public override object GetValue() { return Value; }
}

然后定义与< field> 和其他更高元素相对应的包含类型,如下所示:

Then define the containing type corresponding to <field> and other, higher elements as follows:

[XmlRoot("field", Namespace = XmlNamespaces.Crsoftwareinc)]
[XmlType("field", Namespace = XmlNamespaces.Crsoftwareinc)]
public class Field
{
    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlElement("field-value")]
    public FieldValue FieldValue { get; set; }
}

[XmlRoot("user-defined-data-row", Namespace = XmlNamespaces.Crsoftwareinc)]
[XmlType("user-defined-data-row", Namespace = XmlNamespaces.Crsoftwareinc)]
public class UserDefinedDataRow
{
    [XmlElement("field")]
    public List<Field> Fields { get; set; }
}

// The XML for the root object is not shown so this is just a stub
[XmlRoot("root", Namespace = XmlNamespaces.Crsoftwareinc)]
[XmlType("root", Namespace = XmlNamespaces.Crsoftwareinc)]
public class RootObject
{
    [XmlElement("user-defined-data-row")]
    public List<UserDefinedDataRow> Rows { get; set; }
}

注意:

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆