У меня есть класс 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
.
Я не думаю, что у вас есть способ контролировать имя сгенерированных элементов массива.
Однако, если вы сможете обернуть коллекцию 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());
}
}
У меня была такая же проблема с моим сериализатором.Ни один из приведенных выше ответов не сработал. Я обнаружил, что атрибут 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-сериализация)?
Установите XmlRoot
на Human в:
[XmlRoot("Person")]
Sidebar:
Persons, вероятно, должно быть People
Если у вас нет доступа к исходному тексту класса Human (в этом случае , установка XmlRoot невозможна), вы можете создать XmlElementAttribute, затем добавить его в XmlAttributeOverride и использовать его при создании экземпляра XmlSerializer. Подробнее см. В этой статье MSDN .