Как десерализовать XML-узлы с разными именами до одного и того же базового типа

#c# #xml #attributes #deserialization #nodes

#c# #xml #атрибуты #Десериализация #узлы

Вопрос:

У меня возникли проблемы с поиском примера в Интернете, который объясняет, как именно настроить XmlSerializer для десериализации XML так, как я хочу.

Я хочу десериализовать этот XML в Fruits или, по крайней мере, в List<Fruit>

 <fruits>
  <apple>{fruitstuff}</apple>
  <orange>{fruitstuff}</orange>
  <pear>{fruitstuff}</pear>
<fruits>
  

Я представляю модель, которая выглядит следующим образом

 class Fruits : List<Fruit> {}

class Fruit {
  {fruitstuff}
}

class Apple : Fruit {}

class Orange : Fruit {}

class Pear : Fruit {}
  

Проблема, с которой я сталкиваюсь, заключается в некоторой комбинации конфигурации XmlSerlization и атрибуции XML. Когда я предоставляю XmlSeralizer, XML может быть прочитан без выдачи ошибки, однако он не распознает коллекцию фруктов. Коллекция будет содержать ноль элементов.

 var seralizer = new XmlSerializer(typeof(Fruits), new XmlRootAttribute("Fruits"));
  

Мой вопрос к Интернету в том, как мне настроить сериализатор для распознавания и десериализации похожих узлов в коллекцию базовых типов?

Я бы предпочел иметь тщательно сконфигурированный пользовательский сериализатор, чем XmlAttributed model. Возможно, я захочу использовать модель с другими форматами, отличными от XML. Наличие xml-атрибутов по всей моей модели, я думаю, менее элегантно, чем целевая реализация сериализации.

Ответ №1:

  1. Добавьте <fruit> элемент для переноса нескольких <fruits> элементов
  2. Добавьте атрибуты XmlRoot и XmlElement в соответствующие классы.

Мой пример кода, и он работает:

 class Program
{

    static void Main(string[] args)
    {
        string xml = @"
        <fruit>
            <fruits>
              <apple>
                 <attr1>1</attr1>
                 <attr2>2</attr2>
              </apple>
              <orange>
                 <attr1>3</attr1>
                 <attr2>4</attr2>
              </orange>
              <pear>
                 <attr1>5</attr1>
                 <attr2>6</attr2>
              </pear>
            </fruits> 
            <fruits>
              <apple>
                 <attr1>7</attr1>
                 <attr2>8</attr2>
              </apple>
              <orange>
                 <attr1>9</attr1>
                 <attr2>10</attr2>
              </orange>
              <pear>
                 <attr1>11</attr1>
                 <attr2>12</attr2>
              </pear>
            </fruits>   
        </fruit>
            ";
        var ser = new XmlSerializer(typeof(Fruit));
        using (var reader = new StringReader(xml))
        {
            var myFruits = (Fruit)ser.Deserialize(reader);
        }

        Console.Read();
    }
}


[XmlRoot("fruit")]
public class Fruit
{
    [XmlElement("fruits")]
    public List<Fruits> Fruits { get; set; }
}


public class Fruits
{
    [XmlElement("apple")]
    public Apple Apple { get; set; }

    [XmlElement("orange")]
    public Orange Orange { get; set; }

    [XmlElement("pear")]
    public Pear Pear { get; set; }
}

public class FruitCommonProperty
{
    [XmlElement("attr1")]
    public string Attr1 { get; set; }

    [XmlElement("attr2")]
    public string Attr2 { get; set; }
}

public class Apple : FruitCommonProperty { }

public class Orange : FruitCommonProperty { }

public class Pear : FruitCommonProperty { }
  

Комментарии:

1. Часть проблемы заключается в том, что входной XML — это внешний ввод, который предоставляется как есть. Приведенный пример представляет собой упрощенную версию реальной проблемы. Одним из ограничений является то, что структура XML не поддается изменению. Если бы я мог изменить структуру XML, я бы отформатировал его совершенно по-другому.