代码之家  ›  专栏  ›  技术社区  ›  Sarah Vessels

C#中没有“Key”/“Value”节点的IXmlSerializable字典

  •  2
  • Sarah Vessels  · 技术社区  · 14 年前

    我正在尝试用C#序列化词典。全部 the examples

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

    以及 读取XML :

    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 序列化和反序列化 读取XML ,而我用 WriteElementString

    我的问题是,如何序列化一个字典,使它的XML与上面的第二个XML示例类似,但这样序列化和反序列化 List<MySerializableDictionary> 废话

    1 回复  |  直到 14 年前
        1
  •  2
  •   Sarah Vessels    14 年前

    我的 WriteXml 看起来还可以,因为它以我想要的XML格式输出字典的内容。 ReadXml 是我错的地方。基于 读取XML 找到实现 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添加任何特殊处理,我相信这是必要的。不过,这似乎是个开始。

    编辑: 写作 ,而不是在阅读时。

    更新 上面要说明的代码 XmlNodeType.Whitespace ReadEndElement 当警察来的时候 reader.NodeType 不是一个 XmlNodeType.EndElement 当它是一个 EndElement ,也改变了 while 循环以便读者可以继续(通过 Read() Element 而且它还没有击中目标 亲情 (例如,它击中了 Whitespace