Серіалізація Словаря (Словник) і XML CDATA

Останнім моїм головним болем був елемент CDATA. За завданням потрібно було врахувати можливість, що у полях XML може бути HTML розмітка. А XML для десеріалізації псувати не можна, і ескейпінг теж не підійшов би. Ось і було вирішено використати блок CDATA.

Першими граблями була можливість створення 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. Ось що вийшло:

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

public void ReadXml ( System . Xml . XmlReader reader ) < XmlSerializer keySerializer = new XmlSerializer (typeof (TKey)); XmlSerializer valueSerializer = new XmlSerializer (typeof (TValue));

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

if (wasEmpty) return;

while ( reader. NodeType !=система . Xml. XmlNodeType . EndElement ) < читач. ReadStartElement ( «елемент» );

читач. ReadStartElement ( «ключ» ); Ключ TKey = ( TKey ) keySerializer. Десеріалізація (читач); читач. ReadEndElement ( ); читач. ReadStartElement ( «значення» );

значення TVvalue; if ( typeof ( TValue ) == typeof ( XmlCDataSection ) ) < var o = читач. Значення ; value = ( TValue ) ( object ) ( new XmlDocument ( ) . CreateCDataSection ( o ) ) ; читач. Прочитати ( ); > інакше < value = (TValue) valueSerializer. Десеріалізація (читач); >

читач. ReadEndElement ( ); це . Додати (ключ, значення); читач. ReadEndElement ( ); читач. Перемістити до вмісту (); > читач. ReadEndElement ( ); >

public void WriteXml ( System . Xml . XmlWriter writer ) < XmlSerializer keySerializer = ( typeof ( TKey ) ); XmlSerializer valueSerializer = ( typeof ( TValue ) );

foreach ( ключ TKey у цьому ключі . Keys ) < письменник. WriteStartElement ( «елемент» ); письменник. WriteStartElement ( «ключ» ); серіалізатор ключів. Серіалізація (записувач, ключ); письменник. WriteEndElement ( );

письменник. WriteStartElement ( «значення» ); Значення TValue = this [ ключ ] ; valueSerializer. Серіалізація (автор, значення); письменник. WriteEndElement ( );