XmlSerializer列表项元素名称

Qst*_*onr 37 c# xmlserializer

我上课了 PersonList

[XmlRoot("Persons")]
PersonList : List<Human>
Run Code Online (Sandbox Code Playgroud)

当我将其序列化为XML时,默认情况下会生成如下内容:

<Persons>
  <Human>...</Human>
  <Human>...</Human>
</Persons>
Run Code Online (Sandbox Code Playgroud)

我的问题是需要以改变元素做什么Human,以Person输出?所以输出将是:

<Persons>
  <Person>...</Person>
  <Person>...</Person>
</Persons>
Run Code Online (Sandbox Code Playgroud)

并且,如何将上述XML反序列化为PersonList类对象?

Per Nick的建议,这是我的测试代码:

[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());
    }
}
Run Code Online (Sandbox Code Playgroud)

测试代码的输出是:

<Persons>
  <Human>
    <Name>John</Name>
  </Human>
  <Human>
    <Name>Peter</Name>
  </Human>
</Persons>
Run Code Online (Sandbox Code Playgroud)

由于输出显示,[XmlRoot("Person")]Human没有标签更改为PersonHuman.

tri*_*e84 54

使用以下属性标记您的类:

[XmlType("Account")]
[XmlRoot("Account")]
Run Code Online (Sandbox Code Playgroud)

  • 我发现只有第一个必要,谢谢:) (13认同)
  • 这是正确的答案.其他答案只是解决方法,而这是实际的解决方案! (7认同)
  • 这个解决方案的解释是什么? (2认同)

Joã*_*elo 30

我认为没有办法控制生成的数组元素的名称.

但是,如果您可以将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());
    }
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*eve 15

我的序列化器遇到了同样的问题.上述答案都没有完全奏效.我发现人类的XmlRoot属性明显被忽略,因为它不是文档的根元素.在上下文对象中包装列表对我来说不是一个选项,因为我无法更改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; }
}
Run Code Online (Sandbox Code Playgroud)

使用XmlElement序列化通用列表意味着它不会像XmlArray那样将包装元素放在列表周围,或者像子类一样.它还为您提供了向Persons类添加属性的附加选项,这是我从中获得的想法:

如何向XmlArray元素添加属性(XML序列化)?