XML-сериализатор .NET и строка XHTML в свойстве объекта - PullRequest
0 голосов
/ 11 мая 2019

У меня есть класс

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.7.3081.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://test/v1")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://test/v1", IsNullable=false)]
public partial class Data
{
    ...
    public object Comment { get; set; }
    ...
}

Свойство Comment имеет тип object, поскольку оно объявлено как тип any в схеме xml.Он объявлен как любой, чтобы разрешить как текстовые, так и данные xhtml.Я не могу изменить схему - она ​​связана с международным стандартом.

Однострочный контент (строка):

<Comment>This is a single line text</Comment>

Многострочный контент (xhtml):

<Comment>
   <div xmlns="http://www.w3.org/1999/xhtml">This is text<br />with line breaks<br />multiple times<div>
</Comment>

XmlSerializer не позволит мне подключить XmlElement к свойству object Comment автоматически сгенерированного класса данных.Я также пытался создать собственную реализацию IXmlSerializer для XHtml, но затем необходимо сгенерировать свойство Comment, сгенерированное XSD, в качестве этого точного типа (вместо объекта).

Пользовательский тип XHtml I 'попытка установить свойство Comment выглядит следующим образом:

[XmlRoot]
public class XHtmlText : IXmlSerializable
{
    [XmlIgnore]
    public string Content { get; set; }

    public XmlSchema GetSchema() => null;

    public void ReadXml(XmlReader reader) { } // Only used for serializing to XML

    public void WriteXml(XmlWriter writer)
    {
        if (Content.IsEmpty()) return;

        writer.WriteStartElement("div", "http://www.w3.org/1999/xhtml");
        var lines = Content.Split('\n');
        for (var i = 0; i < lines.Length; i++)
        {
            var line = lines[i];
            writer.WriteRaw(line);
            if (i < lines.Length - 1) writer.WriteRaw("<br />");
        }
        writer.WriteFullEndElement();
    }
}

Исключение из XmlSerializer:

InvalidOperationException: тип Lib.Xml.XHtmlText может не использоваться в этомконтекст.Чтобы использовать Lib.Xml.XHtmlText в качестве параметра, возвращаемого типа или члена класса или структуры, параметр, возвращаемый тип или член должны быть объявлены как тип Lib.Xml.XHtmlText (он не может быть объектом).Объекты типа Lib.Xml.XHtmlText нельзя использовать в нетипизированных коллекциях, таких как ArrayLists

Код сериализации:

    var data = new Lib.Xml.Data { Content = "test\ntest\ntest\n" };

    var settings = new XmlWriterSettings()
    {
        NamespaceHandling = NamespaceHandling.OmitDuplicates,
        Indent = false,
        OmitXmlDeclaration = omitDeclaration,
    };

    using (var stream = new MemoryStream())
    using (var xmlWriter = XmlWriter.Create(stream, settings))
    {
        var serializer = new XmlSerializer(data.GetType(), new[] { typeof(Lib.Xml.XHtmlText) });
        serializer.Serialize(xmlWriter, data);
        return stream.ToArray();
    }

1 Ответ

0 голосов
/ 12 мая 2019

Похоже, я нашел решение.

Я не могу установить комментарий к экземпляру XmlElement

data.Comment = commentAsXhtmlXmlElement;

но я могу (каким-то образом) назначить массив XmlNode

data.Comment = new XmlNode[] { commentAsXhtmlXmlElement };

Обнаружено, когда я десериализировал входящий xml-экземпляр данных POCO.

Странно.

...