Имя элемента элемента списка XmlSerializer

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

[XmlRoot("Persons")]
PersonList : List<Human>

когда я сериализирую это к XML, по умолчанию он произведет что-то вроде этого:

<Persons>
  <Human>...</Human>
  <Human>...</Human>
</Persons>

Мой вопрос - то, какие потребности быть сделанным для изменения элемента Human кому: Person в выводе? таким образом, вывод был бы:

<Persons>
  <Person>...</Person>
  <Person>...</Person>
</Persons>

и, как десериализовать вышеупомянутое XML к PersonList объект класса?

На совет Nick's Вот мой код тестирования:

[XmlRoot("Persons")]
public class Persons : List<Human>
{

}

[XmlRoot("Person")]
public class Human
{
    public Human()
    {
    }

    public Human(string name)
    {
        Name = name;
    }

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

}

void TestXmlSerialize()
{
    Persons personList = new Persons();
    personList.Add(new Human("John"));
    personList.Add(new Human("Peter"));

    try
    {
        using (StringWriter writer = new StringWriter())
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Persons));
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.OmitXmlDeclaration = true;

            XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
            namespaces.Add(string.Empty, string.Empty);

            XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
            serializer.Serialize(xmlWriter, personList, namespaces);

            Console.Out.WriteLine(writer.ToString());
        }
    }
    catch (Exception e)
    {
        Console.Out.WriteLine( e.ToString());
    }
}

Вывод кода тестирования:

<Persons>
  <Human>
    <Name>John</Name>
  </Human>
  <Human>
    <Name>Peter</Name>
  </Human>
</Persons>

Поскольку вывод показывает, [XmlRoot("Person")] на Human не изменяет тег на Person от Human.

37
задан Default 26 February 2013 в 14:59
поделиться

4 ответа

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

Однако, если вы сможете обернуть коллекцию Persons внутри другого класса, у вас будет полный контроль над сгенерированным выводом с помощью XmlArrayAttribute и XmlArrayItemAttribute.

Если вы не можете создать этот новый класс, вы можете прибегнуть к реализации IXmlSerializable, но это гораздо сложнее.

Пример первой альтернативы:

[XmlRoot("Context")]
public class Context
{
    public Context() { this.Persons = new Persons(); }

    [XmlArray("Persons")]
    [XmlArrayItem("Person")]
    public Persons Persons { get; set; }
}

public class Persons : List<Human> { }

public class Human
{
    public Human() { }
    public Human(string name) { Name = name; }
    public string Name { get; set; }
}

class Program
{
    public static void Main(string[] args)
    {
        Context ctx = new Context();
        ctx.Persons.Add(new Human("john"));
        ctx.Persons.Add(new Human("jane"));

        var writer = new StringWriter();
        new XmlSerializer(typeof(Context)).Serialize(writer, ctx);

        Console.WriteLine(writer.ToString());
    }
}
30
ответ дан 27 November 2019 в 04:11
поделиться

У меня была такая же проблема с моим сериализатором.Ни один из приведенных выше ответов не сработал. Я обнаружил, что атрибут XmlRoot класса Human явно игнорируется, поскольку он не является корневым элементом документа. Для меня не было возможности обернуть список в объект контекста, потому что я не могу изменить схему XML. Решение состоит в том, чтобы изменить класс Persons. Вместо того, чтобы создавать подклассы для общего списка, вы оборачиваете его в объект и меняете способ сериализации. См. Пример кода ниже:

[XmlRoot("Persons")]
public class Persons 
{
    public Persons ()
    {
        People = new List<Human>();
    }

    [XmlElement("Person")]
    public List<Human> People 
    { get; set; }
}

public class Human
{
    public Human()
    {
    }

    public Human(string name)
    {
        Name = name;
    }

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

Сериализация вашего общего списка с помощью XmlElement означает, что он не будет помещать элемент оболочки вокруг вашего списка, как это делает XmlArray или как подклассы. Он также дает вам бонусную возможность добавления атрибутов в класс Persons, откуда я и получил эту идею:

Как мне добавить атрибут в элемент XmlArray (XML-сериализация)?

15
ответ дан 27 November 2019 в 04:11
поделиться

Установите XmlRoot на Human в:

[XmlRoot("Person")]

Sidebar:

Persons, вероятно, должно быть People

3
ответ дан 27 November 2019 в 04:11
поделиться

Если у вас нет доступа к исходному тексту класса Human (в этом случае , установка XmlRoot невозможна), вы можете создать XmlElementAttribute, затем добавить его в XmlAttributeOverride и использовать его при создании экземпляра XmlSerializer. Подробнее см. В этой статье MSDN .

1
ответ дан 27 November 2019 в 04:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: