2

C#으로 사전을 serialize하려는 중입니다. 모든 theexamples 나는 다음과 같은 XML 생성 찾을 수있었습니다 :'Key'/ 'Value'노드가없는 C#의 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>를 직렬화 및 역 직렬화 할 경우 역 직렬화 된 목록은 마지막 serializable 사전으로 끝납니다. 뭔가를 멈추어야할지 모르기 때문에 뭔가 읽거나 쓰는 방법에 대해 욕심이 있어야한다고 생각합니다.

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

한 차이 나는 다른 튜토리얼과 어떤 사이에 나타났습니다 여기에 현재 직렬화 사전 List 년대의 직렬화 작동하지 않습니다 내 직렬화 사전 방법은 내가하고있는 일은 많은 사람들이 ReadXmlWriteXml에있는 객체를 직렬화하고 역 직렬화하기 위해 많은 수의 XmlSerializer을 사용하는 반면, 나는 WriteElementString과 같은 것을 사용했다.

내 질문에, 어떻게 그 XML은 위의 두 번째 XML 예제와 같은 사전을 serialize 할 수 있지만 직렬화 및 역 직렬화도 List<MySerializableDictionary> 작동합니까? 심지어 "왜 당신은 멍청한 사람을하고있는 것일까 요?"라는 힌트조차도 도움이 될 것입니다.

+0

사전이 사전 이라고 가정하고 있습니까? – insipid

+0

@insipid, whoops, yes 'Dictionary '입니다. –

답변

1

WriteXml은 사전의 콘텐츠를 원하는 XML 형식으로 출력하기 때문에 괜찮은 것처럼 보였습니다. ReadXml은 내가 잘못 가고있는 곳이었습니다. in this tutorial를 발견 ReadXml 구현을 바탕으로, 나는 다음과 같은 내놓았다 :

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>을 serialize/deserialize하는 테스트도 수행되었습니다. 아직 CDATA에 대한 특별한 처리 방법을 추가하지 않았으므로 필 요할 것입니다. 하지만 이것은 시작처럼 보입니다.

편집 : 실제로, 어쩌면 난 단지 내가 읽을하지 않을 경우, 쓰기있을 때 CDATA에 대해 걱정할 필요.

편집 : 당신이 직렬화 복원 할 때 XML 파일에서 발견된다 XmlNodeType.Whitespace, 설명하기 위해 ReadXml 위의 코드가 업데이트되었습니다. reader.NodeTypeXmlNodeType.EndElement이 아니었을 때 ReadEndElement이 호출 되었기 때문에 XML 오류가 발생했습니다. (그것이 EndElement, 그리고 또한 독자가 (Read() 통해) 진행 할 수 있도록 외부 while 루프를 변경하는 경우에만 ReadEndElement를 호출 그래서이 Element을 명중하지 않은 경우 그 수표에 넣고 그것은 EndElement을 명중하지 않은 예를 들어,, 그것은 Whitespace를 쳤습니다.)

+0

사용자가 "sanitize"해도 잘못된 문자가 포함 된 키를 제공 할 수 있습니다. 이는 XML의 키 고유성에 영향을줍니다. – insipid