【问题标题】:XML Serialization control order on list列表中的 XML 序列化控制顺序
【发布时间】:2013-08-26 17:12:20
【问题描述】:

我正在尝试将以下类序列化为 XML:

[XmlRoot("FCS_SET_SCH")]
public class DDCSendReceiveScheduleXml
{
    private const string TABLE_NAME = "DDCScheduler";

    [XmlElement("schedule",Order=1)]
    public List<ScheduleXml> ScheduleList { get; set; }

    [XmlElement("timetable",Order=2)]
    public List<TimeTableXml> TimeTableXmlList { get; set; }

    public DDCSendReceiveScheduleXml()
    {

    }
}

如果我要分别序列化一个对象,则顺序标志有效,但它似乎无法控制列表中的顺序。

这是 XmlSerializer 目前序列化两个列表的方式:

<FCS_SET_SCH xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <schedule>...</schedule>
   <schedule>...</schedule>
   <timetable>...</timetable>
   <timetable>...</timetable>
</FCS_SET_SCH>

有什么方法可以控制序列化,使上述顺序按此顺序排列?

<FCS_SET_SCH xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <schedule>...</schedule>
   <timetable>...</timetable>
   <schedule>...</schedule>
   <timetable>...</timetable>
</FCS_SET_SCH>

【问题讨论】:

  • 为什么?除非您使用非常严格的解析器,否则 XML 中元素的顺序应该无关紧要。
  • @DStanley 正是如此。这适用于嵌入式设备上的解析器,它在 XML 的排序上有自己荒谬的规则。

标签: c# .net wpf xml serialization


【解决方案1】:

您可以使用ISerializable 来获得对序列化过程的更多控制。当您实现接口时,您可以访问GetObjectData 方法

// Implement this method to serialize data. The method is called  
// on serialization. 
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    var smallest = (TimeTableXmlList.Count < ScheduleList.Count ?? TimeTableXmlList.Count : ScheduleList.Count )
    for(int x = 0; x < smallest; x++)
    {
        var time = TimeTableXmlList.ElementAt(x);
        var schedule = ScheduleList.ElementAt(x)
                // Use the AddValue method to specify serialized values.
        info.AddValue("timetable", time, typeof(TimeTableXml));
        info.AddValue("schedule", schedule , typeof(ScheduleXml));
    }
}

代码示例未经测试

【讨论】:

  • 哦,我喜欢这个主意。
  • 很高兴听到,但我不确定他的设备是否也这么认为^^他必须确认。当然,这个例子并不完美,因为它只允许您使用较小的列表。他必须编辑它以适应他的目的。当他使用这个接口时,他还必须实现流程的其他部分!!!很无力!
  • 这基本上就是我想要的。出于某种原因,它对我不起作用。我需要在正在序列化的类上实现接口对吗?当我在课堂上调用 System.Xml.Serialization.XmlSerializer.Serialize 时,它​​似乎没有进入 GetObjectData 函数。我错过了什么吗? [编辑:啊 nvm。 XmlSerializer 不使用那个接口,我必须使用 IXmlSerializable。我会试一试看看。]
  • 尝试使用SoapFormatterSOAP 基于 XML。您必须使用继承自 IFormatter 的类
  • 哇..我的上帝这两种解决方案都在杀死我,我真的没想到会这么难。我不明白为什么我必须引入大量代码来切换 xml 编写的顺序或为此添加另一个依赖项..
【解决方案2】:

将项目表示为相关,例如 List&lt;KeyValuePair&lt;ScheduleXml, TimeTableXml&gt;&gt; 如果您希望项目配对。

【讨论】:

    【解决方案3】:

    借助有用的答案和 cmets,我最终能够得到正确的解决方案。我在这里发布我所做的事情,以帮助面临类似问题的其他人。

    如果您开始使用 XmlSerializer,那么简单而正确的方法是实现 IXmlSerializable。

    [XmlRoot("FCS_SET_SCH")]
    public class DDCSendReceiveScheduleXml : IXmlSerializable
    {
         ...
        public XmlSchema GetSchema()
        {
            return null;
        }
    
        public void WriteXml(XmlWriter writer)
        {
            Debug.Assert(ScheduleList.Count == TimeTableXmlList.Count, "ScheduleList and TimeTableXml Count isn't same");
            XmlSerializer scheduleSerializer = new XmlSerializer(typeof(ScheduleXml));
            XmlSerializer timeTableSerializer = new XmlSerializer(typeof(TimeTableXml));
            for (int i = 0; i < ScheduleList.Count; i++)
            {
                scheduleSerializer.Serialize(writer, ScheduleList[i]);
                timeTableSerializer.Serialize(writer, TimeTableXmlList[i]);
            }
        }
    

    这会产生我最初想要的结果。当然,这假设您已经为 Xml 序列化标记了两个类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-15
      • 1970-01-01
      • 2012-01-28
      • 2015-08-22
      • 2017-11-20
      • 2019-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多