Серіалізація Словаря (Словник) і 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 ( );