42

I have an XML document similar to the following:

<scan_details>
    <object name="C:\Users\MyUser\Documents\Target1.doc">
        ...
    </object>
    <object name="C:\Users\MyUser\Documents\Target2.doc">
        ...
    </object>
    ...
</scan_details>

I am hoping to use the System.Xml.Serialization attributes to simplify XML deserialization. The issue I have is I cannot work out how to specify that the root node contains an array.

I have tried creating the following classes:

[XmlRoot("scan_details")]
public class ScanDetails
{
    [XmlArray("object")]
    public ScanDetail[] Items { get; set; }
}

public class ScanDetail
{
    [XmlAttribute("name")]
    public string Filename { get; set; }
}

However when I deserialize the XML into the ScanDetails object the Items array remains null.

How do I deserialize an array in a root node?

1 Answer 1

79

You should use [XmlElement], and not [XmlArray] to decorate the Items property - it's already an array, and you only want to set the element name.

public class StackOverflow_12924221
{
    [XmlRoot("scan_details")]
    public class ScanDetails
    {
        [XmlElement("object")]
        public ScanDetail[] Items { get; set; }
    }

    public class ScanDetail
    {
        [XmlAttribute("name")]
        public string Filename { get; set; }
    }

    const string XML = @"<scan_details> 
                            <object name=""C:\Users\MyUser\Documents\Target1.doc""> 
                            </object> 
                            <object name=""C:\Users\MyUser\Documents\Target2.doc""> 
                            </object> 
                        </scan_details> ";

    public static void Test()
    {
        XmlSerializer xs = new XmlSerializer(typeof(ScanDetails));
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(XML));
        var obj = xs.Deserialize(ms) as ScanDetails;
        foreach (var sd in obj.Items)
        {
            Console.WriteLine(sd.Filename);
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Ah... That's confusing terminoligy they use. I'd been focusing on XmlArray and XmlArrayItem. Thanks for that!
If an array, but not just under the root level, then the array property still seems to need [XmlArray("arrayElementName")], and not [XmlElement("arrayElementItemName")], but if under the root level like your answer it needs [XmlElement("arrayElementItemName")] do you know why that is? It's like at the root level you are describing the inner repeating element types, and elsewhere the array type.
I just want to take a moment to thank you. I scoured through many answers on many questions and this is the only thing that works. It is so unintuitive that you don't need to define the array attribute on the root element, nor the array element.
If the element contains sub elements which are all of the same type, or all derived from the same type then you can use XmlElement. If the element contains several different collection with unrelated types, then you'll need to use XmlArray to have a sub element for each collection. This is a detail of XML, you can't have unrelated types in the same collection, the attributes just reflect that.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.