将字典序列化为 XML

Serialising dictionary to XML

我需要准确地生成以下 XML。请注意,每个输入元素必须是字符串或布尔值。

<Userdata version="1.00">
   <ISKeyValueList>
      <Item type="String" key="AgeOfDependents">8,6,1<Item/>
      <Item type="Boolean" key="SecuritiesInPosession"> True </Item>
      <Item type="Boolean" key="SecuritiesOwners"> True </item>
   </ISKeyValueList>
</Userdata> 

除了输入元素,我可以正确生成上面的大部分 XML。我当前的方法生成以下内容:

<Item type="String" key="AgeOfDependents"/>

如您所见,Item 元素不包含文本值 8,6,1。

我目前正在使用以下序列化数据:

对象模型

public class finClient
{
    [XmlAttribute("version")]
    public string version = "1.00";
    public UserData Userdata;
}

public class UserData
{
    [XmlAttribute("version")]
    public string version = "1.00";
    public List<Item> ISKeyValueList;
}

public class Item
{
    [XmlAttribute("type")]
    public string type;
    [XmlAttribute("key")]
    public string key;
}

C#

以下是我如何构造稍后序列化为 XML

的对象
 Userdata = new UserData()
 {
    ISKeyValueList = new List<Item>()
    {
        new Item()
        {
           type = "String", key = "AgeOfDependents"
        }
    }   
 }

我知道向对象模型中的 Item 对象添加另一个元素(例如值)将允许我存储这些值,但是这会将另一个元素添加到 XML 中,这无济于事 XML 需要与顶部显示的完全相同。

我对这个问题的研究让我相信我需要使用 dictionary.Am 我认为我需要字典是正确的?如果是这样,我如何通过对象模型序列化字典。

非常感谢任何能提供帮助的人。

更新

鉴于您的 Item class 可以包含不同类型的原始数据,我建议将其建模为包含类型 IConvertible -- i.e. an object that can be converted from and to a string. Then you can serialize that string value as the character data of each Item element (8,6,1 in your example) by decorating the corresponding property with the [XmlTextAttribute] 属性的对象:

public class Item
{
    TypeCode _type = TypeCode.Empty; // When deserializing, attributes are deserialized before element values, which allows the _type to be set before the XmlValue is read.
    IConvertible _value = null;

    static TypeCode GetItemType(IConvertible value)
    {
        if (value == null)
            return TypeCode.Empty;
        return value.GetTypeCode();
    }

    [XmlAttribute("type")]
    public TypeCode type
    {
        get
        {
            return _type;
        }
        set
        {
            _type = value;
            if (GetItemType(_value) != _type)
                _value = null;
        }
    }

    [XmlAttribute("key")]
    public string key { get; set; }

    [XmlIgnore]
    public IConvertible Value
    {
        get
        {
            return _value;
        }
        set
        {
            _type = GetItemType(value);
            _value = value;
        }
    }

    [XmlText]
    public string XmlValue
    {
        get
        {
            if (_value == null)
                return null;
            return Value.ToString(CultureInfo.InvariantCulture);
        }
        set
        {
            if (value == null)
                _value = null;
            else
            {
                _value = (IConvertible)Convert.ChangeType(value, _type, CultureInfo.InvariantCulture);
            }
        }
    }
}

然后是下面的测试用例:

        string xml = @"<Userdata version=""1.00"">
           <ISKeyValueList>
              <Item type=""String"" key=""AgeOfDependents"">8,6,1</Item>
              <Item type=""Boolean"" key=""SecuritiesInPosession""> True </Item>
              <Item type=""Boolean"" key=""SecuritiesOwners""> True </Item>
           </ISKeyValueList>
        </Userdata>
        ";

        var userdata = xml.LoadFromXML<UserData>();
        Debug.WriteLine(userdata.GetXml(true));

产生以下输出:

<Userdata version="1.00">
    <ISKeyValueList>
        <Item type="String" key="AgeOfDependents">8,6,1</Item>
        <Item type="Boolean" key="SecuritiesInPosession">True</Item>
        <Item type="Boolean" key="SecuritiesOwners">True</Item>
    </ISKeyValueList>
</Userdata>

原答案

您可以将字符串(或其他原始类型或枚举类型)序列化为 character data of an element (8,6,1 in your example) by decorating the corresponding property with the [XmlTextAttribute] 属性。这允许您将额外的 Value 属性 添加到您的 Item class 中,如下所示:

public class Item
{
    [XmlAttribute("type")]
    public string type;
    [XmlAttribute("key")]
    public string key;

    [XmlIgnore] // Do not output the list to XML directly
    public List<int> Values { get; set; }

    [XmlText]  // Instead, output the list as a comma-separated string in the XML element's text value.
    public string XmlValue
    {
        get
        {
            if (Values == null)
                return null;
            return string.Join(",", Values.Select(i => XmlConvert.ToString(i)).ToArray());
        }
        set
        {
            if (value == null)
                Values = null;
            else
            {
                Values = value.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => XmlConvert.ToInt32(s)).ToList();
            }
        }
    }
}

然后是下面的class:

var client = new finClient { Userdata = new UserData { ISKeyValueList = new List<Item> { new Item { type = "String", key = "AgeOfDependents", Values = new List<int> { 8, 6, 1 } } } } };

将被序列化为如下XML:

<finClient version="1.00">
   <Userdata version="1.00">
      <ISKeyValueList>
         <Item type="String" key="AgeOfDependents">8,6,1</Item>
      </ISKeyValueList>
   </Userdata>
</finClient>