【问题标题】:Using XmlSerializer to create a non-standard element使用 XmlSerializer 创建非标准元素
【发布时间】:2010-08-25 15:05:39
【问题描述】:

我正在尝试创建一个 XML 输出文件以导入另一个程序。我收到的示例 XML 文件如下所示:

    <SalesOrder>
  <OrderHeader>
    <BillTo>
      <EntityID>1234</EntityID>
    </BillTo>
  </OrderHeader>
  <LineItemList>
    <OrderLineComment>
      <LineItemID>1</LineItemID>
    </OrderLineComment>
    <LineItem>
      ...
    </LineItem>
    <LineItem>
      ...
    </LineItem>
    <LineItem>
      ...
    </LineItem>
    ...
  </LineItemList>
</SalesOrder>

我有一个 C# 项目,它能够使用 XmlSerializer 输出这种类型的文件,但此部分除外:

  <LineItemList>
    <OrderLineComment>
      <LineItemID>1</LineItemID>
    </OrderLineComment>

LineItemList 部分只是一个 LineItem 列表,但在 LineItemList 的开头添加了这个不同的元素 OrderLineComment。

如果我将它表示为 LineItems 数组,那么它看起来是一样的,只是它缺少 OrderLineComment。如果我将其表示为包含 OrderLineComment 和 LineItems 数组的新对象 LineItemList,我会得到:

  <LineItemList>
    <OrderLineComment>
      <LineItemID>1</LineItemID>
    </OrderLineComment>
    <LineItems>
      <LineItem>
    ...
      </LineItem>
      ...
    </LineItems>

这有我想要的,除了它用&lt;LineItems&gt; 标记包装所有 LineItems,这也不是我想要的。

所以我想知道的是:

  1. 有没有办法通过 XmlSerializer 做到这一点?如果有,怎么做?
  2. 如果没有,并且我必须重写代码以使用 XmlSerializer 以外的其他东西,那么最好的方法是什么?为什么?

提前致谢。

【问题讨论】:

    标签: c# xml xmlserializer


    【解决方案1】:

    您可以使OrderLineCommentLineItem 派生自一个公共基类:

    public abstract class LineItemBase
    {
        ...
    }
    
    public class LineItem : LineItemBase
    {
        ...
    }
    
    public class OrderLineComment : LineItemBase
    {
        ...
    }
    

    然后将LineItemList属性声明为LineItemBase对象的集合,并使用XmlArrayItem属性指定可以包含在集合中的类型:

    [XmlArrayItem(typeof(LineItem))]
    [XmlArrayItem(typeof(OrderLineComment))]
    public List<LineItemBase> LineItemList { get; set; }
    

    这应该可以实现你想要的

    【讨论】:

      【解决方案2】:

      您始终可以在您的类型上实现IXmlSerializable 接口。它允许任何复杂的序列化,并且可以与 XmlSerializer 一起使用。

      编辑:

      如果您想使用标准属性来实现,这里是生成代码的示例。我从您的 xml 创建了 xsd,并使用 XSD.exe 生成了代码。

      [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
      [System.SerializableAttribute()]
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.ComponentModel.DesignerCategoryAttribute("code")]
      [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
      [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
      public partial class SalesOrder {
      
          private OrderHeader orderHeaderField;
      
          private LineItemList lineItemListField;
      
          /// <remarks/>
          public OrderHeader OrderHeader {
              get {
                  return this.orderHeaderField;
              }
              set {
                  this.orderHeaderField = value;
              }
          }
      
          /// <remarks/>
          public LineItemList LineItemList {
              get {
                  return this.lineItemListField;
              }
              set {
                  this.lineItemListField = value;
              }
          }
      }
      
      /// <remarks/>
      [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
      [System.SerializableAttribute()]
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.ComponentModel.DesignerCategoryAttribute("code")]
      [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
      [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
      public partial class OrderHeader {
      
          private BillTo billToField;
      
          /// <remarks/>
          public BillTo BillTo {
              get {
                  return this.billToField;
              }
              set {
                  this.billToField = value;
              }
          }
      }
      
      /// <remarks/>
      [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
      [System.SerializableAttribute()]
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.ComponentModel.DesignerCategoryAttribute("code")]
      [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
      [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
      public partial class BillTo {
      
          private short entityIDField;
      
          /// <remarks/>
          public short EntityID {
              get {
                  return this.entityIDField;
              }
              set {
                  this.entityIDField = value;
              }
          }
      }
      
      /// <remarks/>
      [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
      [System.SerializableAttribute()]
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.ComponentModel.DesignerCategoryAttribute("code")]
      [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
      [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
      public partial class LineItemList {
      
          private OrderLineComment orderLineCommentField;
      
          private string[] lineItemField;
      
          /// <remarks/>
          public OrderLineComment OrderLineComment {
              get {
                  return this.orderLineCommentField;
              }
              set {
                  this.orderLineCommentField = value;
              }
          }
      
          /// <remarks/>
          [System.Xml.Serialization.XmlElementAttribute("LineItem")]
          public string[] LineItem {
              get {
                  return this.lineItemField;
              }
              set {
                  this.lineItemField = value;
              }
          }
      }
      
      /// <remarks/>
      [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
      [System.SerializableAttribute()]
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.ComponentModel.DesignerCategoryAttribute("code")]
      [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
      [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
      public partial class OrderLineComment {
      
          private sbyte lineItemIDField;
      
          /// <remarks/>
          public sbyte LineItemID {
              get {
                  return this.lineItemIDField;
              }
              set {
                  this.lineItemIDField = value;
              }
          }
      }
      

      【讨论】:

      • 赞成,因为在开始尝试后很明显它会达到我正在寻找的结果,只是基类解决方案更快更容易。非常感谢您的回答。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-24
      • 1970-01-01
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      相关资源
      最近更新 更多