XML сериализует массив различных классов с именами пользовательских тегов - PullRequest
2 голосов
/ 17 февраля 2012

Предположим, у меня есть следующая структура класса:

[XmlInclude(typeof(CustomNode))]
[XmlInclude(typeof(CustomNode2))]
[XmlRoot("node")]
class Node
{
    [XmlElement("node")]
    public Node[] Children { get; set; }
}
[XmlRoot("custom-node")]
class CustomNode : Node { }
[XmlRoot("custom-node-2")]
class CustomNode2 : Node { }

Я создаю следующую структуру:

var root = new Node { Children = new Node[2] };
root.Children[0] = new CustomNode();
root.Children[1] = new CustomNode2();

Когда я сериализую эту структуру в XML, я получаю следующий вывод:

<node>
    <node xsi:Type="CustomNode"/>
    <node xsi:Type="CustomNode2"/>
</node>

Но я хотел бы увидеть (и иметь возможность правильно загрузить) что-то вроде этого:

<node>
    <custom-node/>
    <custom-node-2/>
</node>

Возможно ли это вообще для XmlSerializer?Вся проблема в том, что я собираюсь вручную создать исходный XML-код и пытаюсь сделать его более понятным и дружелюбным.

Ответы [ 2 ]

7 голосов
/ 17 февраля 2012

Я нашел решение вашей проблемы, почти то, что вам нужно:

  [XmlRoot(ElementName = "node")]
  public class Node
  {
    [XmlArrayItem(typeof(CustomNode), ElementName = "custom-node")]
    [XmlArrayItem(typeof(CustomNode2), ElementName = "custom-node-2")] 
    public List<Node> Children { get; set; }     
  }
  [XmlRoot(ElementName = "custom-node")]
  public class CustomNode : Node { }
  [XmlRoot(ElementName = "custom-node-2")]
  public class CustomNode2 : Node { }

Результат:

<node xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Children>
    <custom-node />
    <custom-node-2 />
  </Children>
</node>

Надеюсь, это немного поможет.

0 голосов
/ 17 февраля 2012

Я не думаю, что вы сможете убедить XmlSerializer вывести этот xml, если вы используете только различные атрибуты xml для указания xml.

Атрибут [XmlRoot], который вы пытаетесь использовать, игнорируется, если тип не находится в корне (а не составлен в другом классе).

Однако вы можете реализовать интерфейс IXmlSerializable и предоставить реализацию для IXmlSerializable.WriteXml, которую XmlSerializer будет вызывать, если она присутствует.

Это позволит вам создать xml, который вы хотите, прямо в XmlWriter.

Если вам также нужно десериализовать, вам необходимо предоставить эквивалентную реализацию для IXmlSerializable.ReadXml.

...