Использование XmlSerializer для создания нестандартного элемента - PullRequest
0 голосов
/ 25 августа 2010

Я пытаюсь создать выходной файл 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 - это просто список LineItems, но в начале LineItemList находится этот другой элемент OrderLineComment.

Если я представляю это как массив LineItems, то он выглядит так же, за исключением того, что отсутствует OrderLineComment. Если я представлю это как новый объект LineItemList, содержащий OrderLineComment и массив LineItems, я получу это:

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

Имеет то, что я хочу, за исключением того, что он оборачивает все LineItems тегом <LineItems>, что мне тоже не нужно.

Так что мне интересно:

  1. Есть ли способ сделать это через XmlSerializer? Если да, то как?
  2. Если его нет, и мне нужно переписать код, чтобы использовать что-то отличное от XmlSerializer, какой лучший способ сделать это и почему?

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 25 августа 2010

Вы можете сделать OrderLineComment и LineItem производными от общего базового класса:

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; }

Это должно достичь того, что вы хотите

1 голос
/ 25 августа 2010

Вы всегда можете реализовать интерфейс IXmlSerializable для вашего типа.Он допускает сериализацию любой сложности и работает с XmlSerializer.

Edit:

Вот пример сгенерированного кода, если вы хотите достичь его с помощью стандартных атрибутов.Я создал xsd из вашего xml и сгенерировал код с помощью 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;
        }
    }
}
...