将字典序列化为XML

时间:2015-05-21 04:39:08

标签: c# xml dictionary xml-serialization object-model

我需要完全生成以下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对象添加另一个元素,例如Value,这将允许我存储这些值,但这会在XML中添加另一个元素,因为XML需要准确无需帮助与最上面显示的相同。

我对这个问题的研究让我觉得我需要使用字典。我认为我需要一本字典吗?如果是这样,我如何通过对象模型序列化字典。

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

1 个答案:

答案 0 :(得分:0)

<强>更新

鉴于您的Item类可以包含不同类型的原始数据,我建议将其建模为包含IConvertible类型的对象 - 即可以转换的对象来自和到一个字符串。然后,您可以通过使用character data属性修饰相应的属性,将该字符串值序列化为每个Item元素的[XmlTextAttribute](示例中为8,6,1):

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属性修饰相应的属性,将字符串(或其他基元或枚举类型)序列化为元素的[XmlTextAttribute](示例中为8,6,1)。这允许您将额外的Value属性添加到Item类,如下所示:

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

然后是以下课程:

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>