我正在尝试用 C# 序列化字典。全部the examples我已经能够找到如下所示的创建 XML:
<Dictionary>
<ArrayOfEntries>
<Entry>
<Key>myFirstKey</Key>
<Value>myFirstValue</Value>
</Entry>
<Entry>
<Key>mySecondKey</Key>
<Value>mySecondValue</Value>
</Entry>
</ArrayOfEntries>
</Dictionary>
情况各不相同,有时是 ArrayOfEntries
节点不是必需的,但我仍然看到字典的键值对存储在它们自己的节点中的常规模式。我想要的是如下内容:
<Dictionary>
<myFirstKey>myFirstValue</myFirstKey>
<mySecondKey>mySecondValue</mySecondKey>
</Dictionary>
我写了ReadXml
和WriteXml
之前执行此操作并且它适用于单个字典,但是如果我尝试序列化和反序列化 List<T>
在我的可序列化字典实例中,反序列化列表最终仅包含最后可序列化字典。我认为我的读取或写入方法一定是贪婪的,以至于它不知道何时停止。以下是我的可序列化字典方法,目前不适用于 List
的序列化可序列化字典的:
public void WriteXml(XmlWriter writer)
{
foreach (string key in getKeysToSerialize())
{
string cleanKey = key.SanitizeForXml();
string value = getValueForKey(key).Trim();
if (isCdata(key, value))
{
string cdataFriendlyValue = cleanStringForUseInCdata(value);
if (string.IsNullOrEmpty(cdataFriendlyValue))
{
continue;
}
writer.WriteStartElement(cleanKey);
writer.WriteCData(cdataFriendlyValue);
writer.WriteEndElement();
}
else
{
writer.WriteElementString(cleanKey, value);
}
}
}
和ReadXml
:
public void ReadXml(XmlReader reader)
{
string key = null, value = null;
bool wasEmpty = reader.IsEmptyElement;
while (reader.Read())
{
if (wasEmpty)
{
return;
}
switch (reader.NodeType)
{
case XmlNodeType.Element:
key = reader.Name;
if (keyIsSubTree(key))
{
using (XmlReader subReader = reader.ReadSubtree())
{
storeSubtree(key, subReader);
}
// Reset key to null so we don't try to parse it as
// a regular key-value pair later
key = null;
}
break;
case XmlNodeType.Text:
value = reader.Value;
break;
case XmlNodeType.CDATA:
value = cleanCdataForStoring(reader.Value);
break;
case XmlNodeType.EndElement:
if (!string.IsNullOrEmpty(key))
{
string valueToStore =
string.IsNullOrEmpty(value) ? string.Empty : value
Add(key, valueToStore);
}
key = null;
value = null;
break;
}
}
}
我注意到其他教程和我正在做的教程之间的一个区别是许多教程使用 XmlSerializer
序列化和反序列化ReadXml
中的对象和WriteXml
,而我使用 WriteElementString
等等。
我的问题是,如何序列化字典,使其 XML 就像上面的第二个 XML 示例一样,但序列化和反序列化 List<MySerializableDictionary>
也有效吗?即使只是暗示“你为什么要这么做,这可能会让事情变得有趣”也会有所帮助。
最佳答案
我的WriteXml
看起来不错,因为它以我想要的 XML 格式输出字典的内容。 ReadXml
是我出错的地方。基于ReadXml
发现实现in this tutorial ,我想出了以下内容:
public override void ReadXml(XmlReader reader)
{
reader.MoveToContent();
bool isEmptyElement = reader.IsEmptyElement;
reader.ReadStartElement();
if (isEmptyElement)
{
return;
}
while (XmlNodeType.EndElement != reader.NodeType)
{
// Bypass XmlNodeType.Whitespace, as found in XML files
while (XmlNodeType.Element != reader.NodeType)
{
if (XmlNodeType.EndElement == reader.NodeType)
{
reader.ReadEndElement();
return;
}
reader.Read();
}
string key = reader.Name;
if (keyIsSubTree(key))
{
storeSubtree(key, reader.ReadSubtree());
}
else
{
string value = reader.ReadElementString();
storeKeyValuePair(key, value ?? string.Empty);
}
}
if (XmlNodeType.EndElement == reader.NodeType)
{
reader.ReadEndElement();
}
}
这似乎适用于只有一个键值对的字典以及具有多个键值对的字典。我对 List<T>
的序列化/反序列化测试字典也起作用了。我还没有为 CDATA 添加任何特殊处理,我确信这是必要的。不过,这似乎是一个开始。
编辑:实际上,也许我只需要在编写时担心CDATA,而不是在阅读时担心。
编辑:更新ReadXml
上面的代码说明 XmlNodeType.Whitespace
,当您反序列化时可以在 XML 文件中找到它。我收到 XML 错误,因为 ReadEndElement
当 reader.NodeType
被调用时不是XmlNodeType.EndElement
。对此进行检查,以便它只调用 ReadEndElement
当它是EndElement
时,并且还改变了外部while
循环,以便读者在未达到 Read()
时可以继续前进(通过 Element
)而且还没有达到 EndElement
(例如,它已命中 Whitespace
)。
关于c# - C# 中的 IXmlSerialized 字典没有 'Key'/'Value' 节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3523503/