1

I have a weird XML setup here: I need to interface with a third-party and their XML layout that they're using is beyond my control - no chance to changing anything...

In the scope of a larger XML, I find myself needing to serialize (and later also deserialize) a list of items (for a mobile device) which are defined as having a Type and a Number property (both strings). So this would be something like:

public class SerialNumber
{
    public string Type { get; set; }
    public string Number { get; set; }
}

And this would normally serialize a List<SerialNumber> SerialNumbers as

<SerialNumbers>
    <SerialNumber>
        <Type>SN</Type>
        <Number>CBS583ABC123</Number>
    </SerialNumber>
    <SerialNumber>
        <Type>IMEI</Type>
        <Number>35-924106-659945-4</Number>
    </SerialNumber>
</SerialNumbers>        

However, in my case, I need to send this XML:

<SerialNumbers>
    <Type>SN</Type>
    <Number>CBS583ABC123</Number>
    <Type>IMEI</Type>
    <Number>35-924106-659945-4</Number>
</SerialNumbers>        

So basically, the list elements need to be omitted - I just need a container <SerialNumbers> and then for each entry in the list, I only need to serialize out the Type and Number subelements.

How can I do this easily in .NET with the XmlSerializer ?

I tried to use

[XmlRoot(ElementName="")]
public class SerialNumber

or

[XmlArray]
[XmlArrayItem(ElementName = "")]
public List<SerialNumber> SerialNumbers { get; set; }

but neither of these worked - I still get my full serialization with the <SerialNumber> elements inside the <SerialNumbers> container...

Is there an easy trick to achieve what I'm looking for? I'd much rather not go low-level and start concetanating together my XML manually....

Thanks!

1

2 Answers 2

3

You could use custom serialization with IXmlSerializable.

public class SerialNumbers : List<SerialNumber>, IXmlSerializable
{
    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        Clear();
        reader.ReadStartElement();
        while (reader.NodeType != XmlNodeType.EndElement)
        {
            var serialNumber = new SerialNumber
            {
                Type = reader.ReadElementContentAsString("Type", ""),
                Number = reader.ReadElementContentAsString("Number", "")
            };
            Add(serialNumber);
        }
        reader.ReadEndElement();
    }

    public void WriteXml(XmlWriter writer)
    {
        foreach (var serialNumber in this)
        {
            writer.WriteElementString("Type", serialNumber.Type);
            writer.WriteElementString("Number", serialNumber.Number);
        }
    }
}

public class SerialNumber
{
    public string Type { get; set; }
    public string Number { get; set; }
}

Example:

var ser = new XmlSerializer(typeof(SerialNumbers));

var reader = new StringReader(@"
    <SerialNumbers>
        <Type>SN</Type>
        <Number>CBS583ABC123</Number>
        <Type>IMEI</Type>
        <Number>35-924106-659945-4</Number>
    </SerialNumbers>
".Trim());
var result = (SerialNumbers) ser.Deserialize(reader);

var writer = new StringWriter();
ser.Serialize(writer, result);

Result:

<?xml version="1.0" encoding="utf-16"?>
<SerialNumbers>
  <Type>SN</Type>
  <Number>CBS583ABC123</Number>
  <Type>IMEI</Type>
  <Number>35-924106-659945-4</Number>
</SerialNumbers>
Sign up to request clarification or add additional context in comments.

Comments

0

This might do the trick for you

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class SerialNumbers
{
    private string[] itemsField;
    private ItemsChoiceType[] itemsElementNameField;
    [System.Xml.Serialization.XmlElementAttribute("Number", typeof(string))]
    [System.Xml.Serialization.XmlElementAttribute("Type", typeof(string))]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
    public string[] Items
    {
        get
        {
            return this.itemsField;
        }
        set
        {
            this.itemsField = value;
        }
    }

    [System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public ItemsChoiceType[] ItemsElementName
    {
        get
        {
            return this.itemsElementNameField;
        }
        set
        {
            this.itemsElementNameField = value;
        }
    }
}

[System.Xml.Serialization.XmlTypeAttribute(IncludeInSchema = false)]
public enum ItemsChoiceType
{
    Number,
    Type,
}

1 Comment

Sorry, no this doesn't work at all - I keep getting "Reflection errors" when trying to serialize this......

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.