C# 将列表序列化为 XML,并自动生成序列属性

本文关键字:自动生成 属性 XML 列表 序列化 | 更新日期: 2023-09-27 18:35:08

我必须从具有(Order)元素数组的对象生成(序列化为)XML。从 XSD 生成的订单类具有序列属性:

    [System.Xml.Serialization.XmlAttributeAttribute(DataType = "token")]
    public string Sequence;

我使用的是.Net XMLSerializer,但它不会为每个订单元素序列属性自动生成。

具有:

 Order[] Orders = new Order[2] {...}

我必须得到:

<Order Sequence="1">..</Order>
<Order Sequence="2">..</Order>

对于一个单一的元素,它应该呈现:

    <Order Sequence="1">..</Order>

有谁知道如何使XMLSerialzier自动呈现此属性?还是我需要为每个订单元素手动设置序列?

干杯

C# 将列表序列化为 XML,并自动生成序列属性

AFAIK 没有办法用开箱即用的方法实现这一点。这为您提供了以下选项:

IXml可序列化

在包含订单数组的对象上实现 IXmlSerializable。这样,您可以手动序列化订单,也可以在使用 XmlSerializer 将对象序列化到XmlWriter之前设置订单的序列号。序列化方法:

public class OrdersContainer : IXmlSerializable
{
    public Order[] Orders;
    public void WriteXml(XmlWriter writer)
    {
        // Serialize other properties
        writer.WriteStartElement("Orders");
        var ser = new XmlSerializer(typeof(Order));
        for(var i = 0; i < Orders.Length; i++)
        {
            Orders[i].Sequence = (i + 1).ToString();
            ser.Serialize(writer, Orders[i]);
        }
        writer.WriteEndElement(); // Orders
    }
    // ...
}

这将生成以下 XML:

<?xml version="1.0" encoding="utf-16"?>
<OrdersContainer>
  <Orders>
    <Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Sequence="1">
      <Name>Order 1</Name>
    </Order>
    <Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Sequence="2">
      <Name>Order 2</Name>
    </Order>
  </Orders>
</OrdersContainer>

XmlSerializer 将一些命名空间声明放在 Order 元素上,但这并没有什么坏处。我的示例类在Order类上具有Name属性。

此方法的缺点是必须手动实现 OrdersContainer 类的序列化,包括反序列化。

Linq to XML

第二个选项是将 Linq to XML 用于序列化部分。您还必须手动实现序列化,但您可以使用 otb XmlSerializer 进行反序列化(另一方面,您可能希望避免混合使用两个不同的框架)。您可以按如下方式序列化 OrdersContainer 类,也可以写入序列号:

var doc = new XDocument(new XElement("OrdersContainer", 
    new XElement("Orders", 
        cont.Orders.Select((x, i) => new XElement("Order", 
            new XAttribute("Sequence", (i + 1).ToString()), 
            new XElement("Name", x.Name))))));
doc.Save(writer);

这将创建以下 XML:

<?xml version="1.0" encoding="utf-16"?>
<OrdersContainer>
  <Orders>
    <Order Sequence="1">
      <Name>Order 1</Name>
    </Order>
    <Order Sequence="2">
      <Name>Order 2</Name>
    </Order>
  </Orders>
</OrdersContainer>

请注意,该示例使用 Select 方法的重载,该方法还接收项的索引,以便可以根据数组中的位置创建序列号。

如果 order 是你的类,你可以添加一个属性 [XmlAttributeAttribute]

class Order {
    [XmlAttribute()]
    public int Sequence { get; set; }

但是,您应该在列表的所有项中设置此 Sequence 属性。

这工作正常 -

var o = new XmlSerializerNamespaces();
o.Add("", "");
var ser = new XmlSerializer(typeof(List<Order>), "");

using (var sw = new StringWriter())
{
     ser.Serialize(sw, new List<Order> { 
                new Order { sequence = "1", MyProperty = 1 }, 
                new Order { sequence = "2", MyProperty = 2 } },
                o);
     var t = sw.ToString();
}

AND 
[XmlAttribute(AttributeName = "sequence", DataType = "string")]
public string sequence { get; set; }