将字典序列化为 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>
我需要准确地生成以下 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>