2

我试图序列化C#中的字典。所有theexamples我已经能够找到创建XML这样的:在C#中没有'Key'/'Value'节点的IXmlSerializable字典

<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> 

我已经写ReadXmlWriteXml之前做到这一点,它适用于一个单一的词典,但如果我尝试序列化和反序列化我的序列化的词典实例的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来序列化和反序列化它们的ReadXmlWriteXml中的对象,而我使用的是WriteElementString等。

我的问题是,我如何序列化一个字典,使其XML像上面我的第二个XML例子,但这样序列化和反序列化List<MySerializableDictionary>也适用?即使只是暗示“为什么你在做那么,这可能会让它变得有趣”会有所帮助。

+0

我们是否假设你的字典是一个Dictionary 这里? – insipid 2010-08-19 17:44:18

+0

@insipid,whoops,是的,它是'Dictionary '。 – 2010-08-19 18:25:42

回答

1

我的WriteXml似乎没问题,因为它输出我想要的XML格式的字典内容。 ReadXml是我出错的地方。基于发现in this tutorialReadXml实现,我想出了以下内容:

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

这似乎为字典是只有一个键值对,以及与多个键值对字典的工作。我对字典序列化/反序列化的测试也奏效。我还没有为CDATA添加任何特殊处理,我相信这是必要的。虽然这似乎是一个开始。

编辑:其实,也许我只需要担心CDATA当我写作,看的不是时候。

编辑:更新上面ReadXml代码占XmlNodeType.Whitespace,这是在XML文件中发现,当你反序列化。我得到一个XML错误,因为当reader.NodeType不是XmlNodeType.EndElement时,ReadEndElement被调用。放入了一个检查,以便它仅调用ReadEndElement当它是一个EndElement,也改变外while循环,使读者能够取得进展(通过Read())时,它并没有触及Element,也没有打一个EndElement(例如它击中了Whitespace)。

+0

尽管您“清理”它们,但用户还可以为其提供具有无效字符的键。这会影响XML中键的唯一性。 – insipid 2010-08-19 19:10:50