XmlSerializer.Deserialize - проблема со смешанным содержимым (mixed content)

Всем привет.

Хочу десериализовать следующую строку:

<summary>
    Initializes a new instance of the <see cref="T:PrimarkPOSAutoTests.WinAppDriver"/> class.
</summary>

Падает на этой строке со следующим исключением:

XmlException: 'Element' is an invalid XmlNodeType.

Хочу десериализовать эту строку как сплошной string. Можно ли так сделать? Или сериализатор путается из-за тэга <see/>?

P.S. Поле для хранения этого текста:

[XmlElement(ElementName = "summary")]
public string Summary { get; set; }

Ответы (1 шт):

Автор решения: Pavel Mayorov

Для начала, надо понять, что содержимое тэга <summary> - это не строка! Это структурированный текст, который должен быть представлен в виде фрагмента DOM.

Простейший способ считать его - это сделать свойство типа object:

[XmlElement(ElementName = "summary")]
public object Summary { get; set; } // реальный тип - XmlNode[]

Теперь в свойство Summary попадёт массив XmlNode[] из трёх узлов - XmlText, XmlElement и снова XmlText.

Однако, работать с таким нетипизированным полем неудобно, поэтому можно попытаться добавить больше типизации. К сожалению, просто поставить XmlNode[] в качестве типа не получится, а значит нужен отдельный класс:

[XmlElement(ElementName = "summary")]
public Summary Summary { get; set; }

public class Summary 
{
    [XmlAnyElement, XmlText]
    public XmlNode[] Nodes { get; set; }
}

Если вы не желаете работать с DOM - можно завести свои типы для десериализации:

public class Summary
{
    [XmlElement("see", Type = typeof(See))]
    [XmlText(Type = typeof(string))]
    public object[] Nodes { get; set; } // реальный тип - (See | string)[]
}

public class See
{
    [XmlAttribute("cref")]
    public string CRef { get; set; }
}

Наконец, если вам обязательно требуется получить именно строковое представление - можно сделать вот так:

[XmlElement("summary")]
public RawXml Summary { get; set; }

public class RawXml : IXmlSerializable
{
    public string Content { get; set; }

    XmlSchema IXmlSerializable.GetSchema() => null;

    void IXmlSerializable.ReadXml(XmlReader reader)
    {
        Content = reader.ReadInnerXml();
    }

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        writer.WriteRaw(Content);
    }
}

Но без нужды так лучше не делать: вы рискуете запутаться в префиксах и пространствах имён.

→ Ссылка