Последней моей головной болью был элемент CDATA. По заданию нужно было учесть возможность, что в полях XML может присутствовать HTML разметка. А xml для десериализации портить нельзя, и эскейпинг тоже не подошел бы. Вот и было решено использовать блок CDATA.
Первыми граблями было отсутствие возможности создания CDATA при трансформации XSLT. Где-то читал, что если формат на выходе не XML:
<xsl:output method="xml" indent="yes"/>
то можно использовать тег <xsl:cdata>... не пробовал.
Хоть w3c предусматривает CDATA для элементов (добавлением аттрибутов cdata-section-elements в xsl:output):
<xsl:output method="xml" indent="yes" cdata-section-elements="element1 element2" />
это не работает когда пытаюсь вставить 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<TKey, TValue>: Dictionary<TKey, TValue>, IXmlSerializable
{ public System.
Xml.
Schema.
XmlSchema GetSchema
() { return null;
} 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 !=
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(TValue
) ==
typeof(XmlCDataSection
)) { var o = reader.
Value;
value =
(TValue
) (object)(new 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 =
new XmlSerializer
(typeof(TKey
));
XmlSerializer valueSerializer =
new XmlSerializer
(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;