- Хроники. - http://usanov.net -

Сериализация Словаря (Dictionary) и XML CDATA.

Posted By Ikutsin On 5 июня 2008 @ 11:11 In .NET C# | Comments Disabled

Последней моей головной болью был элемент CDATA. По заданию нужно было учесть возможность, что в полях XML может присутствовать HTML разметка. А xml для десериализации портить нельзя, и эскейпинг тоже не подошел бы. Вот и было решено использовать блок CDATA [1].

Первыми граблями было отсутствие возможности создания CDATA при трансформации XSLT. Где-то читал, что если формат на выходе не XML:

то можно использовать тег … не пробовал.
Хоть w3c предусматривает CDATA для элементов (добавлением аттрибутов cdata-section-elements в xsl:output):

это не работает когда пытаюсь вставить XML элементы.
Решением было сделать еще обработчик, уже с помощью кода:

foreach (XmlNode contentValue in ContentValues)
{
contentValue.InnerXml = doc.CreateCDataSection(contentValue.InnerXml).OuterXml;
}

Все бы хорошо, да вот как известно, System.Collections.Generic.Dictionary не сериализируется, по этому нужен свой класс сериализации. Его не составило проблемы найти, правда был у него один недостаток, не хотел он десиареализировать класс XmlCDataSection, возвращая null. Сериализация по умолчанию работала, значит необходимо было править код SerializableDictionary. Вот что получилось:

using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;

public class SerializableDictionary: Dictionary, IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema()
{

return null;

}

public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new [2] XmlSerializer(typeof [3](TKey));
XmlSerializer valueSerializer = new [2] XmlSerializer(typeof [3](TValue));

bool wasEmpty = reader.IsEmptyElement;
reader.Read();

if (wasEmpty) return;

while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement(«item»);

reader.ReadStartElement(«key»);
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement(«value»);

TValue value;
if (typeof [3](TValue) == typeof [3](XmlCDataSection))
{
var o = reader.Value;
value = (TValue) (object)(new [2] XmlDocument().CreateCDataSection(o));
reader.Read();
} else
{
value = (TValue)valueSerializer.Deserialize(reader);
}

reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}

public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = (typeof [2](TKey));
XmlSerializer valueSerializer = (typeof(TValue));

foreach (TKey key in this.Keys)
{
writer.WriteStartElement(«item»);
writer.WriteStartElement(«key»);
keySerializer.Serialize(writer, key);
writer.WriteEndElement();

writer.WriteStartElement(«value»);
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();

writer.WriteEndElement();
}

}
}

Теперь на выходе можно было получать html, который не был эскейпан и игнорировался обычными XML парсерами.
А достать содержимое можно так: Content.First().Value.Value;


Article printed from Хроники.: http://usanov.net

URL to article: http://usanov.net/60-serializaciya-slovarya-dictionary-i-xml-cdata

URLs in this post:

[1] CDATA: http://www.w3schools.com/XML/xml_cdata.asp

[2] new: http://www.google.com/search?q=new+msdn.microsoft.com

[3] typeof: http://www.google.com/search?q=typeof+msdn.microsoft.com

Copyright © 2008 Все, что меня окружает. All rights reserved.