【问题标题】:With XmlSerializer, how to set element names for a List?使用 XmlSerializer,如何为 List 设置元素名称?
【发布时间】:2018-06-11 16:55:59
【问题描述】:

我似乎无法让 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&lt;DriveData&gt; 上什么都不做。我的DriveData 类上的[XmlElement(ElementName = "HardDrive")] 会导致构建错误。如何将根和 &lt;HardDrive&gt; 元素名称设置为我想要的?

【问题讨论】:

  • Google XML 序列化程序属性,您将属性应用到您的属性并在该属性中指定名称。特别是 Array 和 ArrayItem。
  • 您的示例 XML 不清楚。您想要一个名为&lt;HardDrives&gt; 的单亲和多个&lt;HardDrive&gt; 的子代吗?
  • 是的。我的应用程序检索计算机硬盘驱动器上的数据。根“HardDrives”元素将包含一个或多个“HardDrive”元素,具体取决于运行它的系统。

标签: c# xml xmlserializer


【解决方案1】:

你可以保留你的模型。在创建序列化程序对象时,使用类的 XmlType 属性和第二个参数作为 new 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();
    }      
}

【讨论】:

    【解决方案2】:

    虽然XmlSerializer 可以 直接序列化List&lt;T&gt;,就像您对new XmlSerializer(typeof(List&lt;DriveData&gt;)) 所做的那样,但代价是您不能对生成的元素名称做太多事情。更好的方法是将列表包装到一个类中,该类的属性如下:

    [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&lt;DriveData&gt; 嵌入到更复杂的结构中,另一种方法是使用[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>
    

    【讨论】:

      【解决方案3】:

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

      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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-05
        相关资源
        最近更新 更多