c# XmlSerializer:保留值,覆盖元素标签

本文关键字:覆盖 元素 标签 XmlSerializer 保留 | 更新日期: 2023-09-27 18:18:08

我目前正在使用LINQ查询读取XML文件,例如

<MyObjects>
   <MyObject>
       <MyElement>some_text</MyElement>
       <MyOtherElement>some_more_text</MyOtherElement>
   </MyObject>
</MyObjects>

转换为包含自定义HistoryString属性的自定义对象列表。HistoryString包含两个字符串,一个currentValue和一个previousValue

这一切都很好,除了当使用XmlSerializer将自定义对象写回XML文件时,输出相当明显地包含额外的标记,即

<MyObjects>
   <MyObject>
       <MyElement>
                  <currentValue>some_text</currentValue>
                  <previousValue>some_text</previousValue>
       </MyElement>
       <MyOtherElement>
                  <currentValue>some_more_text</currentValue>
                  <previousValue>some_more_text</previousValue>
       </MyOtherElement>
   </MyObject>
</MyObjects>

问:基于这种基本差异,以相同格式读写XML的最简洁和/或最有效的方法是什么?

一些初步的想法:

1)用[System.Xml.Serialization.XmlIgnore]标记previousValue属性,然后扫描要写的XML字符串,删除<currentValue></currentValue>的所有痕迹

2)打开现有的文件,手动进行任何更新/删除/添加-这肯定更冗长。

3)有一个HistoryString自动解析到它的currentValue,而不是序列化它的每个属性的任何方法,类似于ToString()的工作方式?

我对此做了一些研究,包括有用的MSDN文章在这里和在这里,但我看不到任何其他属性可以解决这个问题,我仍然不确定这是否可能。什么好主意吗?

c# XmlSerializer:保留值,覆盖元素标签

这是另一个想法。如果你这样定义你的类:

[Serializable]
public class MyObject
{
    [XmlElement(ElementName = "MyElement")]
    public string CurrentValueElement
    {
        get
        {
            return Element.CurrentValue;
        }
        set
        {
            Element = new MyElement
                          {
                              CurrentValue = value, PreviousValue = value
                          };
        }
    }
    [XmlElement(ElementName = "MyOtherElement")]
    public string CurrentValueOtherElement
    {
        get
        {
            return OtherElement.CurrentValue;
        }
        set {}
    }
    [XmlIgnore]
    public MyElement Element { get; set; }
    [XmlIgnore]
    public MyElement OtherElement { get; set; }
}

然后,当对象被序列化时,输出的XML将与您的示例完全相同。

同样,如果你像这样扩展CurrentValueElement/CurrentValueOtherElement setter:

[XmlElement(ElementName = "MyElement")]
public string CurrentValueElement
{
    get
    {
        return Element.CurrentValue;
    }
    set
    {
        Element = new MyElement
                      {
                          CurrentValue = value, PreviousValue = value
                      };
    }
}

然后,您将能够使用XmlSerializer直接反序列化您的对象,而无需诉诸LINQ。

那么,为什么不使用原始模式进行序列化,并将仅使用当前值的历史转换对象列表馈送给它呢?

from h in HistoryEntryList
select new OriginalEntry{ field = h.field.current_value, ... };