Последней моей головной болью был элемент 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. Вот что получилось:
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 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 = (typeof(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;
Метки:C#, разработка
Похожие статьи
- 8 июля 2008 -- Исправляем HTML для чтения как XML. (5)
- 31 августа 2009 -- CRUD на SQLite (5)
- 6 февраля 2009 -- Загрузка Flash в Windows.Forms и WPF. (2)
- 30 декабря 2008 -- Создаем ASHX хендлер в ASP.NET (1)
- 8 марта 2011 -- C#: Silverlight таймаут (Timeout) (2)
31 мая, 2011 at 6:06
Спасибо за статью. Исправьте, пожалуйста, кавычки на корректные с точки зрения синтаксиса 🙂
И
XmlSerializer keySerializer = (typeof(TKey));
XmlSerializer valueSerializer = (typeof(TValue));
поправить 🙂
Для полного счастья хотелось бы увидеть небольшой пример использования 🙂