Joseph Anderson
Joseph Anderson

Reputation: 4144

Nest XML Elements - XML Serialization

I need to sandwich an element inside of another element. Is it possible to serialize XML like this?

http://pastebin.com/7qDE7Ses

Here is my class

[XmlRoot(ElementName = "SalesOrderMod")]
public partial class SalesOrderMod
{
    [XmlElementAttribute(Order = 1)]
    public string TxnID { get; set; }
    [XmlElementAttribute(Order = 2)]
    public string EditSequence { get; set; }
    [XmlElementAttribute(Order = 3)]
    public string ShipDate { get; set; }
    [XmlElementAttribute(Order = 4)]
    public ListRef ShipMethodRef = new ListRef();

    public bool ShouldSerializeShipMethodRef()
    {
        return !(String.IsNullOrEmpty(ShipMethodRef.FullName));
    }

    [XmlElementAttribute(Order = 5)]
    public string Other { get; set; }

    [XmlElementAttribute(Order = 6, ElementName = "SalesOrderLineMod")]
    public List<LineMod> SalesOrderLineMod = new List<LineMod>();

    [XmlElementAttribute(Order = 7, ElementName = "SalesOrderLineGroupMod")]
    public List<LineMod> SalesOrderLineGroupMod = new List<LineMod>();
}

Upvotes: 0

Views: 110

Answers (1)

dbc
dbc

Reputation: 116615

You originally indicated you would like to serialize a series of elements inside an XML document like so:

<SalesOrderLineRet>
</SalesOrderLineRet>
<SalesOrderLineGroupRet>
</SalesOrderLineGroupRet>
<SalesOrderLineRet>
</SalesOrderLineRet>

You can if the types that correspond to SalesOrderLineRet and SalesOrderLineGroupRet have some common base type T, and they are stored in a List<T>. For instance, the following class definitions:

public abstract class SalesOrderLineRetBase
{
}

public class SalesOrderLineRet : SalesOrderLineRetBase
{
}

public class SalesOrderLineGroupRet : SalesOrderLineRetBase
{
}

public class RootObject
{
    [XmlElement(typeof(SalesOrderLineRetBase))]
    [XmlElement(typeof(SalesOrderLineRet))]
    [XmlElement(typeof(SalesOrderLineGroupRet))]
    public List<SalesOrderLineRetBase> SalesOrders { get; set; }
}

Will, when serialized, produce the following XML:

<RootObject>
    <SalesOrderLineRet />
    <SalesOrderLineGroupRet />
</RootObject>

Using [XmlElement(typeof(T))] tells XmlSerializer that the list should be serialized without an outer container element, and that items of type T can be expected to be found in the list. You must apply [XmlElement(typeof(T))] once for each type T that will be stored in the list.

(You can use List<object> if the types in the list have no other more derived base type, however I don't recommend that. I would instead recommending grouping the possible types of list entry under a specific base type.)

If you would prefer your list to be serialized with an outer container element, you can use [XmlArray] and [XmlArrayItem(typeof(T))]:

public abstract class SalesOrderLineRetBase
{
}

public class SalesOrderLineRet : SalesOrderLineRetBase
{
}

public class SalesOrderLineGroupRet : SalesOrderLineRetBase
{
}

public class RootObject
{
    [XmlArray("SalesOrders")]
    [XmlArrayItem(typeof(SalesOrderLineRetBase))]
    [XmlArrayItem(typeof(SalesOrderLineRet))]
    [XmlArrayItem(typeof(SalesOrderLineGroupRet))]
    public List<SalesOrderLineRetBase> SalesOrders { get; set; }
}

Which produces the following XML:

<RootObject>
    <SalesOrders>
        <SalesOrderLineRet />
        <SalesOrderLineGroupRet />
    </SalesOrders>
</RootObject>

You must apply [XmlArrayItem(typeof(T))] for each type T that will be stored in the list.

(Since you don't include the relevant classes and XML in your question, I'm not sure which one you might want.)

Upvotes: 1

Related Questions