Member 13229879 Ответов: 2

Десериализация XML-массива


Я получил десериализацию, работая с одним элементом. Но когда у меня есть массив 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>

ДТО
[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; }
}

Ниже приведен код для десериализации:
CarDetails[] details;
XmlSerializer serializer = new XmlSerializer(typeof(CarDetails[]));
using (TextReader reader = new StringReader(output))
{
    details = (CarDetails[])serializer.Deserialize(reader);
}

2 Ответов

Рейтинг:
2

Graeme_Grant

Во-первых, у вас есть проблема с недопустимым конечным тегом-здесь:

<color>blue<color>

должно быть:
<color>blue</color>

то же самое с:
<color>white<color>

должно быть:
<color>white</color>

Далее вам нужно сгенерировать классы для вашего XML. Вот два варианта:

Вариант 1. (Предпочтительный)

Вот полезный инструмент для создания классов из XML: [^]

Генерирует это:
/* 
    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; }
    }

}

Вариант 2.

Кроме того, Visual Studio (протестированная на VS2017) также может генерировать классы из XML:
1. скопируйте XML-данные в буфер обмена
2. В ВС редактировать &ГТ; Специальная вставка &ГТ; "вставить XML в классы"

Генерирует это:
/// <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;
        }
    }
}

Так что на ваш вопрос, Вариант 1. использование для сбора автомобилей:
[XmlElement(ElementName="cars")]
public List<Cars> Cars { get; set; }

и Вариант 2. использует:
private dataCars[] carsField;

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

Что можно было бы упростить следующим образом:
private dataCars[] carsField;

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


Рейтинг:
2

RickZeeland

Я думаю, что вы можете сделать это так, но вам, возможно, придется изменить свой класс, чтобы это сработало, я просто использовал "нормальный" класс с публичными свойствами:

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