反序列化 xml,包括命名空间

Posted

技术标签:

【中文标题】反序列化 xml,包括命名空间【英文标题】:Deserializing xml, including namespace 【发布时间】:2015-11-03 07:16:34 【问题描述】:

我正在尝试反序列化一些 XML,但我无法让命名空间 /xsi:type="Model" 工作。如果xsi:type="Model" 被排除在XML 之外,它就可以工作,但它必须存在。如果我将命名空间留在模型之外,我会得到一个错误,如果我重命名它,我会得到一个空列表。

XML

<Vehicles xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Vehicle xsi:type="Model">
        <Id>238614402</Id>
    </Vehicle>
    <Vehicle xsi:type="Model">
        <Id>238614805</Id>
    </Vehicle>
</Vehicles>

型号

[XmlRootAttribute("Vehicles")]
public class Vehicles

    public Vehicles() 
    
        Vehicle = new List<Vehicle>();
    

    [XmlElement(ElementName = "Vehicle", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public List<Vehicle> Vehicle  get; set; 



public class Vehicle

    [XmlElement("Id")]
    public int Id  get; set; 


反序列化

XmlSerializer serializer = new XmlSerializer(typeof(Vehicles));
string carXML = "<Vehicles xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><Vehicle  xsi:type=\"Model\"> <Id>238614402</Id> </Vehicle><Vehicle  xsi:type=\"Model\"> <Id>238614805</Id> </Vehicle></Vehicles>";

var cars = (Vehicles)serializer.Deserialize(new StringReader(carXML));

上面的例子返回一个空列表,因为命名空间是错误的,据我所知 - 我如何让它返回一个实际的列表?

编辑 我对 XML 没有任何控制权,我是从不同的提供商那里获得的,所以我必须相应地更改其余代码。

【问题讨论】:

“但它必须在那里” - 不,它没有。您的示例中 Vehicle 元素的命名空间不是 http://www.w3.org/2001/XMLSchema-instance - 在您的 xml 的 Vehicles 元素中,该命名空间已与 xsd 命名空间前缀相关联 - 但没有应用这样的前缀Vehicle 中的元素。因此,它位于全局命名空间中。 感谢您的回复,如果我将命名空间留在模型之外,我会收到以下错误:无法识别指定的类型:name='Model', namespace='', at . [InvalidOperationException:无法识别指定的类型:name='Model',namespace='',在 。] 【参考方案1】:

请试试这个:

public partial class Vehicles

    [XmlElement("Vehicle")]
    public Vehicle[] Vehicle  get; set; 


[XmlInclude(typeof(Model))]
public partial class Vehicle

    public uint Id  get; set; 


public class Model : Vehicle  

注意输入vehicle

var xs = new XmlSerializer(typeof(Vehicles));
Vehicles vehicles;

using (var fs = new FileStream("file.xml", FileMode.Open))

    vehicles = (Vehicles)xs.Deserialize(fs);


foreach (var vehicle in vehicles.Vehicle)

    Console.WriteLine(vehicle.GetType()); // Model
    Console.WriteLine(vehicle.Id);

无需指定命名空间。序列化属性xsi时会自动添加实际类型Model

xs.Serialize(Console.Out, vehicles);

【讨论】:

以上是关于反序列化 xml,包括命名空间的主要内容,如果未能解决你的问题,请参考以下文章

C# 在忽略命名空间的同时反序列化 xml

由于命名空间而无法反序列化 xml

C# 使用多个可能的命名空间反序列化 xml

反序列化自定义 XML 时出现 InvalidOperationException(缺少命名空间)

如何在 .NET 中的反序列化期间指定 XML 序列化属性以支持命名空间前缀?

包含命名空间的xml反序列化 (1.7环境下)