Click here to Skip to main content
15,888,351 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I got deserializing working with single element. But when I have array of xml elements, my code is not working.

Below is my code

What I have tried:

XML
<data>
    <cars>
        <body>
            <color>blue<color>
            <type>sedan</type>
        </body>
        <details>
            <year>2016</year>
            <make>Infiniti</make>
        </details>
    </cars>
    <cars>
        <body>
            <color>white<color>
            <type>SUV</type>
        </body>
        <details>
            <year>2016</year>
            <make>Lexus</make>
        </details>
    </cars>
</data>

Dto
C#
[XmlRoot("cars")]
public class CarDetails
{
	[XmlElement("body")]
	public Body BodyList { get; set; }

	[XmlElement("details")]
	public DetailsList details { get; set; }
}

public class Body
{
	public string Color { get; set; }
	public string Type { get; set; }
}

public class DetailsList
{
	public int Year { get; set; }
	public string Make { get; set; }
}

Below is the code for deserializing:
C#
CarDetails[] details;
XmlSerializer serializer = new XmlSerializer(typeof(CarDetails[]));
using (TextReader reader = new StringReader(output))
{
    details = (CarDetails[])serializer.Deserialize(reader);
}
Posted
Updated 18-Sep-17 16:05pm
v3

First, you have a problem with an invalid ending tag - here:
XML
<color>blue<color>

should be:
XML
<color>blue</color>

same with:
XML
<color>white<color>

should be:
XML
<color>white</color>

Next, You need to generate classes for your XML. Here are two options:

Option 1. (Preferred)

Here is a useful tool to generate classes from XML: [^]

Generates this:
C#
/* 
    Licensed under the Apache License, Version 2.0
    
    http://www.apache.org/licenses/LICENSE-2.0
    */
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
    [XmlRoot(ElementName="body")]
    public class Body {
        [XmlElement(ElementName="color")]
        public string Color { get; set; }
        [XmlElement(ElementName="type")]
        public string Type { get; set; }
    }

    [XmlRoot(ElementName="details")]
    public class Details {
        [XmlElement(ElementName="year")]
        public string Year { get; set; }
        [XmlElement(ElementName="make")]
        public string Make { get; set; }
    }

    [XmlRoot(ElementName="cars")]
    public class Cars {
        [XmlElement(ElementName="body")]
        public Body Body { get; set; }
        [XmlElement(ElementName="details")]
        public Details Details { get; set; }
    }

    [XmlRoot(ElementName="data")]
    public class Data {
        [XmlElement(ElementName="cars")]
        public List<Cars> Cars { get; set; }
    }

}

Option 2.

Also, Visual Studio (tested on VS2017) can also generate classes from XML:
1. Copy XML data to the clipboard
2. In VS, Edit > Paste Special > "Paste Xml as classes"

Generates this:
C#
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class data
{

    private dataCars[] carsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("cars")]
    public dataCars[] cars
    {
        get
        {
            return this.carsField;
        }
        set
        {
            this.carsField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class dataCars
{

    private dataCarsBody bodyField;

    private dataCarsDetails detailsField;

    /// <remarks/>
    public dataCarsBody body
    {
        get
        {
            return this.bodyField;
        }
        set
        {
            this.bodyField = value;
        }
    }

    /// <remarks/>
    public dataCarsDetails details
    {
        get
        {
            return this.detailsField;
        }
        set
        {
            this.detailsField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class dataCarsBody
{

    private string colorField;

    private string typeField;

    /// <remarks/>
    public string color
    {
        get
        {
            return this.colorField;
        }
        set
        {
            this.colorField = value;
        }
    }

    /// <remarks/>
    public string type
    {
        get
        {
            return this.typeField;
        }
        set
        {
            this.typeField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class dataCarsDetails
{

    private ushort yearField;

    private string makeField;

    /// <remarks/>
    public ushort year
    {
        get
        {
            return this.yearField;
        }
        set
        {
            this.yearField = value;
        }
    }

    /// <remarks/>
    public string make
    {
        get
        {
            return this.makeField;
        }
        set
        {
            this.makeField = value;
        }
    }
}

So for your question, Option 1. uses for the collection of cars:
C#
[XmlElement(ElementName="cars")]
public List<Cars> Cars { get; set; }

and Option 2. uses:
C#
private dataCars[] carsField;

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("cars")]
public dataCars[] cars
{
    get
    {
        return this.carsField;
    }
    set
    {
        this.carsField = value;
    }
}

Which could be simplified as:
C#
private dataCars[] carsField;

/// <remarks/>
[System.Xml.Serialization.XmlElement("cars")]
public dataCars[] cars
{
    get => carsField;
    set => carsField = value;
}
 
Share this answer
 
v3
I think you can do it like this, but you might have to change your class for this to work, I just used a "normal" class with public properties:
string xml = File.ReadAllText(@"test.xml");
List<CarDetails> res = new List<CarDetails>();
var serializer = new XmlSerializer(res.GetType());

using (TextReader reader = new StringReader(xml))
{
	res = (List<CarDetails>)serializer.Deserialize(reader);
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900