【问题标题】:C# XmlSerializer: keep the value, override the element labelC# XmlSerializer:保留值,覆盖元素标签
【发布时间】:2011-12-16 12:22:23
【问题描述】:

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

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

到包含自定义HistoryString 属性的自定义对象列表中。 HistoryString 包含 2 个字符串,一个 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 字符串,删除&lt;currentValue&gt;&lt;/currentValue&gt; 的所有痕迹

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

3) 有什么方法可以让HistoryString 自动解析为它的currentValue,而不是像 ToString() 的工作方式那样序列化它的每个属性?

我对此进行了一些研究,包括有用的 MSDN 文章 herehere 但我看不到任何其他可以解决此问题的属性,我仍然不确定这是否可能。有什么想法吗?

【问题讨论】:

    标签: c# xml xml-serialization


    【解决方案1】:

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

    [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 设置器:

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

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

    【讨论】:

      【解决方案2】:

      那么为什么不使用原始模式进行序列化,并仅使用当前值将历史转换后的对象列表输入其中?

      例如

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

      【讨论】:

      • 对我来说听起来不错,我对 LINQ 还很陌生,所以让我看看我能不能弄点东西。目前我正在做 XElement.Load(path) 然后在途中构建一个查询,但在回来的路上只使用 XmlSerializer 将它们序列化为 StreamWriter。
      • 如果你有原始 xml 的架构(我怀疑你这样做,因为你使用 linq 查询它)你可以使用 XmlSerializer 将列表转换回 xml,它只是转换你的问题hsitory 列表到“原始”对象列表中,上面的 linq 为您完成。
      猜你喜欢
      • 1970-01-01
      • 2016-04-19
      • 1970-01-01
      • 2021-12-26
      • 2015-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多