Опрос десериализованных объектов - PullRequest
1 голос
/ 06 апреля 2019

Имея этот XML, содержащий коллекцию автомобилей:

<?xml version="1.0" encoding="utf-8"?>
<CarCollection>
    <Cars>
        <Car>
            <StockNumber>1020</StockNumber>
            <Make>Nissan</Make>
            <Model>Sentra</Model>
        </Car>
        <Car>
            <StockNumber>1010</StockNumber>
            <Make>Toyota</Make>
            <Model>Corolla</Model>
        </Car>
        <Car>
            <StockNumber>1111</StockNumber>
            <Make>Honda</Make>
            <Model>Accord</Model>
        </Car>
        <Car>
            <StockNumber>2000</StockNumber>
            <Make>Maybach</Make>
            <Model>S 600</Model>
        </Car>
        <Car>
            <StockNumber>2001</StockNumber>
            <Make>Ferrari</Make>
            <Model>F355 Spider</Model>
        </Car>
    </Cars>
</CarCollection>

и его десериализованные классы объектов, сгенерированные xsd.exe:

//------------------------------------------------------------------------------
// <auto-generated>
//     Dieser Code wurde von einem Tool generiert.
//     Laufzeitversion:4.0.30319.42000
//
//     Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
//     der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------

using System.Xml.Serialization;

// 
// Dieser Quellcode wurde automatisch generiert von xsd, Version=4.6.1055.0.
// 


/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class CarCollection : object, System.ComponentModel.INotifyPropertyChanged {

    private CarCollectionCars[] itemsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Cars", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public CarCollectionCars[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
            this.RaisePropertyChanged("Items");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class CarCollectionCars : object, System.ComponentModel.INotifyPropertyChanged {

    private CarCollectionCarsCar[] carField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Car", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public CarCollectionCarsCar[] Car {
        get {
            return this.carField;
        }
        set {
            this.carField = value;
            this.RaisePropertyChanged("Car");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class CarCollectionCarsCar : object, System.ComponentModel.INotifyPropertyChanged {

    private string stockNumberField;

    private string makeField;

    private string modelField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string StockNumber {
        get {
            return this.stockNumberField;
        }
        set {
            this.stockNumberField = value;
            this.RaisePropertyChanged("StockNumber");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string Make {
        get {
            return this.makeField;
        }
        set {
            this.makeField = value;
            this.RaisePropertyChanged("Make");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string Model {
        get {
            return this.modelField;
        }
        set {
            this.modelField = value;
            this.RaisePropertyChanged("Model");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

Я хочу запросить класс StockNumber, Марка и Модель автомобиля. Следовательно, Я начал с этого кода:

XmlSerializer ser = new XmlSerializer(typeof(CarCollection));
CarCollection cars;
using (XmlReader reader = XmlReader.Create(file))
{
    cars = (CarCollection)ser.Deserialize(reader);
    foreach (var item in cars.Items)
    {
        foreach (var carCollection in item.Car)
        {
            carPool.Add(new CarPool()
            {
                Make = carCollection.Make,
                Model = carCollection.Model,
                StockNumber = carCollection.StockNumber
            });
        }
    }
}

Тем не менее, мне не нравится это гнездо для циклов. Кто-нибудь знает, как сделать запрос более эффективным с помощью LINQ?

Ответы [ 2 ]

2 голосов
/ 06 апреля 2019

Linq и SelectMany () должны разрешать вложенные циклы:

// not tested or compiled
using (XmlReader reader = XmlReader.Create(file))
{
    var cars = (CarCollection)ser.Deserialize(reader);

    carPool.AddRange(
       cars.Items.SelectMany(it => it.Car).Select(c => 
            new CarPool()
            {
                Make = c.Make,
                Model = c.Model,
                StockNumber = c.StockNumber
            }) );
}
2 голосов
/ 06 апреля 2019

Если вы хотите проанализировать XML и если вы используете XmlSerializer, то вам нужно управлять иерархией классов и ее утомительным заданием для управления иерархией классов для сложных и больших xml

Так что одним из вариантов является использование XDocument,

Вы можете просто LINQ на XDocument, чтобы получить нужные данные из XML.

Используя XDocument, вы можете напрямую сконцентрироваться на своих данных без управления структурой класса.

XDocument xdoc = XDocument.Load(@"Path to your xml file");

var result = (from car in xdoc.Descendants("Car")
              select new
              {
                  StockNumber = car.Element("StockNumber")?.Value,
                  Make = car.Element("Make")?.Value,
                  Model = car.Element("Model")?.Value
              }).ToList();


Console.WriteLine("StockNumber\tMake\t\tModel");
Console.WriteLine("----------------------------------------------");
foreach (var item in result)
{
    Console.WriteLine(item.StockNumber + "\t\t" + item.Make + "\t\t" + item.Model); ;
}

Альтернатива:

Тем не менее, вы хотите десериализовать свой XML с помощью XmlSerializer, а классы, приведенные ниже, представляют собой структуру классов,

[XmlRoot("Car")]
public class Car
{
    [XmlElement("StockNumber")]
    public string StockNumber { get; set; }
    [XmlElement("Make")]
    public string Make { get; set; }
    [XmlElement("Model")]
    public string Model { get; set; }
}
[XmlRoot("Cars")]
public class Cars
{
    [XmlElement("Car")]
    public List<Car> Car { get; set; }
}
[XmlRoot("CarCollection")]
public class CarCollection
{
    [XmlElement("Cars")]
    public Cars Cars { get; set; }
}

Использование:

XmlSerializer ser = new XmlSerializer(typeof(CarCollection));

CarCollection cars = null;

using (StreamReader reader = new StreamReader(@"Path to your xml file"))
{
    cars = (CarCollection)ser.Deserialize(reader);
}

List<Car> result = cars.Cars.Car.ToList();

//--------------------------Print the result to console--------------

Console.WriteLine("StockNumber\tMake\t\tModel");
Console.WriteLine("----------------------------------------------");
foreach (var item in result)
{
    Console.WriteLine(item.StockNumber + "\t\t" + item.Make + "\t\t" + item.Model); ;
}

Console.ReadLine();

Выход:

enter image description here

...