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

8

我正在尝试反序列化一些XML,但是我无法让命名空间/xsi:type="Model"生效。如果将xsi:type="Model"从XML中省略,则可以工作,但必须包含它。如果将命名空间从我的Model中省略,我会收到一个错误,如果重命名它,则会得到一个空列表。

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,我从另一个提供者那里获取它,所以我必须相应地更改代码。


2
“但它必须在那里” - 不,不是这样的。在您的示例中,“Vehicle”元素的命名空间不是“http://www.w3.org/2001/XMLSchema-instance” - 在您的xml的“Vehicles”元素中,该命名空间已与“xsd”命名空间前缀相关联 - 但未应用此类前缀到其中的“Vehicle”元素。因此,它在全局命名空间中。 - Damien_The_Unbeliever
谢谢您的回复。如果我在我的模型中省略命名空间,我会得到以下错误:指定的类型未被识别:name='Model',namespace='',位于 <Vehicle xmlns=''>。[InvalidOperationException: 指定的类型未被识别:name='Model',namespace='',位于 <Vehicle xmlns=''>。] - forte
1个回答

7
请尝试以下方法:
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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接