Десериализовать значение элемента как строку, хотя оно содержит смешанное содержимое - PullRequest
5 голосов
/ 04 января 2012

Предполагая, что XML такой:

<my:Root xmlns:my="http://foo/bar">
    <my:FieldBasic>content</my:FieldBasic>
    <my:FieldComplex>
        <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
            <div><h1>content</h1></div>
        </html>
    </my:FieldComplex>
<my:Root>

и класс вроде:

[Serializable]
[XmlType(AnonymousType = true, Namespace = "http://foo/bar")]
[XmlRoot(ElementName = "Root", Namespace = "http://foo/bar", IsNullable = false)]
public class MyRoot
{
    public string FieldBasic { get; set; }
    public string FieldComplex { get; set; }
}

Как мне десериализовать <my:FieldComplex> в строку в FieldComplex? Сбой, когда он находит HTML внутри. Я хочу, чтобы это дало мне строку с этим содержанием:

<html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
    <div><h1>content</h1></div>
</html>

Если я объявляю FieldComplex как public object FieldComplex (т.е. xsd:anyType), это вроде работает, и я получаю XMLNode[], внутри которого я могу использовать.

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

<my:Root xmlns:my="http://foo/bar">
    <my:FieldBasic>content</my:FieldBasic>
    <my:FieldComplex>content</my:FieldComplex>
<my:Root>

Объявление FieldComplex как объекта, который вставит эти атрибуты в элемент <my:FieldComplex>:

 xmlns:q1="http://www.w3.org/2001/XMLSchema" p3:type="q1:string" xmlns:p3="http://www.w3.org/2001/XMLSchema-instance

и я этого не хочу. Я также не хочу использовать разные классы для сериализации и десериализации.

Итак, возможно ли это?

Короче говоря, , возможно ли иметь этот класс:

public class MyRoot
{
    public string FieldBasic { get; set; }
    public string FielComplex { get; set; }
}

Сериализуйте к этому:

<my:Root xmlns:my="http://foo/bar">
    <my:FieldBasic>content</my:FieldBasic>
    <my:FieldComplex>content</my:FieldComplex>
<my:Root>

и десериализовать из этого:

<my:Root xmlns:my="http://foo/bar">
    <my:FieldBasic>content</my:FieldBasic>
    <my:FieldComplex>
        <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
            <div><h1>content</h1></div>
        </html>
    </my:FieldComplex>
<my:Root>

P.S. Просто чтобы объяснить «почему?». У меня ведьма класса получает сериализацию. Затем сериализованный XML проходит через несколько узлов приложения и в конечном итоге возвращается, но изменяется, как указано выше. Слои выполняют некоторую проверку XML и, имея дополнительные атрибуты или элементы на входе, не проходят проверку и останавливают поток. Я хочу сопоставить возвращаемый XML с тем же классом. Контент - это просто строки с его точки зрения, но, конечно, не то же самое для сериализации / десериализации: (

Ответы [ 2 ]

3 голосов
/ 05 января 2012

Это не совсем закончено, потому что я не могу вспомнить, можете ли вы / как добавить префикс пространства имен к корневому элементу в сериализации Xml.Но если вы реализуете интерфейс IXmlSerializable в своем классе MyRoot следующим образом:

[XmlRoot("Root", Namespace="http://foo/bar")]
public class MyRoot : IXmlSerializable

Затем напишите методы сериализации XML самостоятельно, что-то вроде этого:

        void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
        {
            reader.MoveToContent();
            var outerXml = reader.ReadOuterXml();
            XElement root = XElement.Parse(outerXml);

            this.FieldBasic = root.Elements(XName.Get("FieldBasic", "http://foo/bar")).First().Value;
            this.FieldComplex = root.Elements(XName.Get("FieldComplex", "http://foo/bar")).First().Elements().First().Value.Trim();
        }



        void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteRaw(String.Format("\r\n\t<my:FieldBasic>\r\n\t\t{0}\r\n\t</my:FieldBasic>", this.FieldBasic));
            writer.WriteRaw(String.Format("\r\n\t<my:FieldComplex>\r\n\t\t{0}\r\n\t</my:FieldComplex>\r\n", this.FieldComplex));
        }

(вернуть null из GetSchemamethod)

Это должно как минимум приблизить вас к тому, что вы ищете.

Эти ссылки также могут оказаться полезными.

IXmlSerializable

Пространства имен

3 голосов
/ 04 января 2012

Вы можете использовать CDATA в XML, чтобы указать, что содержимое является строковым литералом:

<my:Root xmlns:my="http://foo/bar">
  <my:FieldBasic>content</my:FieldBasic>
  <my:FieldComplex>
    <![CDATA[
      <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
        <div><h1>content</h1></div>
      </html>
    ]]>
  </my:FieldComplex>
</my:Root>
...