使用XmlSerializer,如何设置List的元素名称?

时间:2018-06-11 16:56:00

标签: c# xml xmlserializer

我似乎无法使XmlSerializer属性起作用。我有

public class DriveData
{
    public string Model { get; set; }
    public string Type { get; set; }
    public int SizeGB { get; set; }
    public string SerialNumber { get; set; }
    public bool IsOK { get; set; }
}
static List<DriveData> DiskDrives { get; set; }
XmlSerializer serializer = new XmlSerializer(typeof(List<DriveData>));
FileStream xmlFile = File.Create("DiskDrives.xml");
serializer.Serialize(xmlFile, DiskDrives);
xmlFile.Close();

我想要的是:

<?xml version="1.0" encoding="utf-8" ?>
<HardDrives>
    <HardDrive>
        <Model>Seagate1</Model>
        ...
</HardDrive>
<HardDrive>
    ...
</HardDrive>

但我得到的是:

<?xml version="1.0"?>
<ArrayOfDriveData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <DriveData>
    <Model>Seagate1</Model>
    <Type>SATA</Type>
    <SizeGB>999</SizeGB>
    ...
  </DriveData>
  <DriveData>
    ...
  </DriveData>
</ArrayOfDriveData>
[XmlElement(ElementName = "HardDrives")]上的

List<DriveData>什么也没做。我的[XmlElement(ElementName = "HardDrive")]类上的DriveData会导致构建错误。如何将根和<HardDrive>元素名称设置为我想要的名称?

3 个答案:

答案 0 :(得分:0)

虽然XmlSerializer 可以直接序列化List<T>,但就像使用new XmlSerializer(typeof(List<DriveData>))一样,权衡取舍是你无法做多少生成的元素的名称。更好的方法是将列表包装成一个类,如下所示:

[XmlRoot("HardDrives")]
public class DiskDrives
{
    [XmlElement("HardDrive")]
    public List<DriveData> Drives { get; set; }
}

[XmlRoot]属性表示顶级文档元素,而[XmlElement]属性控制属性的序列化方式。

XmlSerializer生成的XML将如下所示:

<?xml version="1.0" encoding="utf-16"?>
<HardDrives xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <HardDrive>
    <Model>WD</Model>
    …
  </HardDrive>
  <HardDrive>
    <Model>Seagate</Model>
    …
  </HardDrive>
</HardDrives>

如果您将List<DriveData>嵌入到更复杂的结构中,则替代方法是使用[XmlArray][XmlArrayItem]属性来控制IEnumerable属性的方式是序列化的,以及哪些元素名称应用于其项目。以下数据结构:

[XmlRoot("Inventory")]
public class Inventory
{
    … more properties here…

    [XmlArray("HardDrives")]
    [XmlArrayItem("HardDrive")]
    public List<DriveData> Drives { get; set; }
}
然后

会产生这样的XML:

<?xml version="1.0" encoding="utf-16"?>
<Inventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  … more properties would be serialized here …
  <HardDrives>
    <HardDrive>
      <Model>WD</Model>
      …
    </HardDrive>
    <HardDrive>
      <Model>Seagate</Model>
      …
    </HardDrive>
  </HardDrives>
</Inventory>

答案 1 :(得分:0)

可能有更好的方法来实现这一目标,但这是另一种方法。

private static void GenerateXml()
{
        List<DriveData> DiskDrives = new List<DriveData>();
        DiskDrives.Add(new DriveData() { Model = "model1", Type = "type1", SizeGB = 10, SerialNumber = "20155", IsOK = false });
        DiskDrives.Add(new DriveData() { Model = "model2", Type = "type2", SizeGB = 20, SerialNumber = "20165", IsOK = true });

        var newDoc = new XDocument(new XDeclaration("1.0", null, "yes"));
        XElement xmlElements = new XElement("HardDrives",
            from item in DiskDrives
            select new XElement("HardDrive",
                new XElement("Model", item.Model),
                new XElement("Type", item.Type),
                new XElement("SizeGB", item.SizeGB),
                new XElement("SerialNumber", item.SerialNumber),
                new XElement("IsOK", item.IsOK)));
        newDoc.Add(xmlElements);
        newDoc.Save(@"C:\sample.xml");
}

输出XML:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<HardDrives>
  <HardDrive>
    <Model>model1</Model>
    <Type>type1</Type>
    <SizeGB>10</SizeGB>
    <SerialNumber>20155</SerialNumber>
    <IsOK>false</IsOK>
  </HardDrive>
  <HardDrive>
    <Model>model2</Model>
    <Type>type2</Type>
    <SizeGB>20</SizeGB>
    <SerialNumber>20165</SerialNumber>
    <IsOK>true</IsOK>
  </HardDrive>
</HardDrives>

答案 2 :(得分:0)

你可以保留你的模特。在创建序列化程序对象时,将类和第二个参数的XmlType属性用作新的XmlRootAttribute(“HardDrives”)。

[XmlType("HardDrive")]
public class DriveData
{
    public string Model { get; set; }
    public string Type { get; set; }
    public int SizeGB { get; set; }
    public string SerialNumber { get; set; }
    public bool IsOK { get; set; }
}

class Program
{
    static List<DriveData> DiskDrives  { get; set; } = new List<DriveData>();

    static void Main(string[] args)
    {
        DiskDrives.Add(new DriveData { Model = "Seagate1", Type = "SATA", SizeGB = 999 });
        DiskDrives.Add(new DriveData { Model = "Seagate2", Type = "SATA", SizeGB = 777 });

        XmlSerializer serializer = new XmlSerializer(typeof(List<DriveData>), new XmlRootAttribute("HardDrives"));
        FileStream xmlFile = File.Create("DiskDrives.xml");

        serializer.Serialize(xmlFile, DiskDrives);
        xmlFile.Close();

        Console.Read();
    }      
}