【问题标题】:How to Deserialize XML Attributes into objects, then iterate through the objects如何将 XML 属性反序列化为对象,然后遍历对象
【发布时间】:2018-10-15 14:07:05
【问题描述】:

我希望能够对 XML 文件中的车辆“做事”。理想情况下,我想遍历所有车辆并计算它们的价格,并更改它们是否是 OnSale。然后这些值将显示在 UI 中。我的代码反序列化了 XML 文件,但我无法访问 Vehicle 的任何属性。我不需要将对象序列化回 XML。

我尝试 Console.WriteLine 价格,但是当我运行代码时它返回为 0。我应该创建一个 ResponseGeographyVendorRegionVehicle 数组吗?然后以某种方式将该类型的对象添加到数组中?

这是 XML 文件:

<?xml version="1.0" encoding="utf-8" ?>
<Response>
  <Geography>
    <Vendor id="JOHN">
      <Region id="1"></Region>
      <Region id="2">
        <Vehicle Make="HONDA" Fuel="Gas" Price="12000" OnSale="Y" Account="JOHNH" />
        <Vehicle Make="ACURA" Fuel="Gas" Price="14100" OnSale="Y" Account="JOHNH" />
        <Vehicle Make="TOYOTA" Fuel="Gas" Price="8000" OnSale="N" Account="JOHNH" />
        <Vehicle Make="HYUNDAI" Fuel="Gas" Price="13000" OnSale="Y" Account="JOHNH" />
        <Vehicle Make="INFINITY" Fuel="Gas" Price="16000" OnSale="N" Account="JOHNH" />
      </Region>
      <Region id="3"></Region>
      <Region id="4"></Region>
    </Vendor>
  </Geography>
</Response>

这是我的 Program.cs:

namespace XMLDeserializeExample
{
    class Program 
    {
        static void Main(string[] args)
        {
            string path = @"c:\XMLFile1.xml";
            XmlRootAttribute xRoot = new XmlRootAttribute();
            xRoot.ElementName = "Response";
            XmlSerializer ser = new XmlSerializer(typeof(ResponseGeographyVendorRegionVehicle), xRoot);
            ResponseGeographyVendorRegionVehicle i;
            using (Stream reader = new FileStream(path,FileMode.Open)) 
            {
                i = (ResponseGeographyVendorRegionVehicle)ser.Deserialize(reader);
                Console.WriteLine(i.Price);
                Console.ReadLine();
            }
        }

    }
}

这是创建的 Paste Special Response.CS 文件:

namespace XMLDeserializeExample
{
}

// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Response
{

    private ResponseGeography geographyField;

    /// <remarks/>
    public ResponseGeography Geography
    {
        get
        {
            return this.geographyField;
        }
        set
        {
            this.geographyField = value;
        }
    }
}

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ResponseGeography
{

    private ResponseGeographyVendor vendorField;

    /// <remarks/>
    public ResponseGeographyVendor Vendor
    {
        get
        {
            return this.vendorField;
        }
        set
        {
            this.vendorField = value;
        }
    }
}

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ResponseGeographyVendor
{

    private ResponseGeographyVendorRegion[] regionField;

    private string idField;

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

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string id
    {
        get
        {
            return this.idField;
        }
        set
        {
            this.idField = value;
        }
    }
}

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ResponseGeographyVendorRegion
{

    private ResponseGeographyVendorRegionVehicle[] vehicleField;

    private byte idField;

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

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public byte id
    {
        get
        {
            return this.idField;
        }
        set
        {
            this.idField = value;
        }
    }
}

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ResponseGeographyVendorRegionVehicle
{

    private string makeField;

    private string fuelField;

    private ushort priceField;

    private string onSaleField;

    private string accountField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string Make
    {
        get
        {
            return this.makeField;
        }
        set
        {
            this.makeField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string Fuel
    {
        get
        {
            return this.fuelField;
        }
        set
        {
            this.fuelField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public ushort Price
    {
        get
        {
            return this.priceField;
        }
        set
        {
            this.priceField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string OnSale
    {
        get
        {
            return this.onSaleField;
        }
        set
        {
            this.onSaleField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string Account
    {
        get
        {
            return this.accountField;
        }
        set
        {
            this.accountField = value;
        }
    }
}

请让我知道如何更好地解释自己。抱歉,如果这些都没有意义 - 欢迎来到我的周末哈哈。

谢谢。

【问题讨论】:

  • 您的序列化程序应该序列化 xml-root,它是 Response 的一个实例,而不是 ResponseGeographyVendorRegionVehicle:new XmlSerializer(typeof(Response), xRoot);:
  • 当我这样做时,智能感知开始为我提供一直到区域的属性。从地区我无法访问“车辆”属性。使用 Console.WriteLine(i.Geography.Vendor.Region.ToString());
  • 当然,这就是序列化程序的工作方式。你不能只取一段 xml,要么序列化/反序列化所有内容,要么什么都不序列化。然而这有什么问题呢?您可以反序列化响应并仅使用相关信息。

标签: c# xml visual-studio xmlserializer


【解决方案1】:

由于您的 xml-root 显然是 Response 而不是 ResponseGeographyVendor,因此您必须反序列化为该类型:

string path = @"c:\XMLFile1.xml";
XmlSerializer ser = new XmlSerializer(typeof(response);
ResponseGeographyVendor i;
using (Stream reader = new FileStream(path,FileMode.Open)) 
{
    i = ((Response)ser.Deserialize(reader)).Geography.Vendor;
    Console.WriteLine(i.Price);
    Console.ReadLine();
}

序列化程序只适用于整个 xml 文档。你不能只写或读它的一部分。所以只需使用 xml,将其序列化为 Response 的实例并获取其 Geography-member。

现在您可以在第二个Region 中轻松获得第三个Vehicle

var vehicle = i.Region[1].Vehicle[2];

请注意,您不需要自己提供 xml-root。

【讨论】:

  • 很高兴知道我自己不需要 xml-root。你能运行 i = ((Response)ser.Deserialize(reader)).Geography.vendorfield; ?当我尝试将其他属性用于供应商字段时,我无法将其归结为 Vehicle。我收到错误:无法将类型“ResponseGeographyVendorRegion[]”隐式转换为“ResponseGeographyVendorRegionVehicle”
  • 哦,我更正了我的答案。当然属性Vendor 的类型是ResponseGeographyVendor
  • 非常感谢。 var 车辆 = i.Region[1].Vehicle[2];部分也很关键。
【解决方案2】:

您需要使用 .Net 中内置的 XML 序列化器。

首先创建一个类来表示 XML 文档数据:

public class Response
{
      public Geography Geography {get; set;}
}
public class Geography
{
       public Vendor Vendor{get;set;}
}
public class Vendor
{
      public List<Region> Regions {get;set;}
}
public class Region
{
}

等等。 然后将xml读取为字符串并反序列化:

string myXml = File.ReadAsStringAsync(filepath).Result;
XmlSerializer ser = new XmlSerializer(typeof(Response));
using (TextReader reader = new StringReader(myXml)
{
Response myResponse = ser.Deserialize(reader);
}

然后您可以遍历 Geography 对象上的所有属性和内容。

【讨论】:

  • 这会导致类似“Response 不是预期的”,因为 xml-root 是 Response,而不是 Geography
  • 感谢您回复我。 File.ReadAsString 仅是 Async 方法吗?我在 Microsoft 文档中找不到它。
  • @HimBromBeere 我用响应对象更新了它。
  • @adventuresncode 是的,抱歉,我输入得太快了,是的,它是异步的,但你可以执行 readstringasync()。结果 - 我编辑了上面的代码以反映这一点。
猜你喜欢
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 2017-08-20
  • 2020-05-10
  • 1970-01-01
  • 2014-08-22
  • 1970-01-01
相关资源
最近更新 更多