Deserializing xml, including namespace
Asked Answered
S

1

8

I am trying to deserialize some XML and I can't get the namespace / xsi:type="Model" to work. If xsi:type="Model" is left out of the XML it works, but it has to be there. If I leave the namespace out of my Model, I get an error, if I rename it, I get an empty list.

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>

Model

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

}

Deserializing

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

The example above returns an empty list, because the namespace is wrong, as far as I know - how do I get it to return an actual list?

EDIT I don't have any control over the XML, I'm getting that from a different provider, so I will have to change the rest of the code accordingly.

Satiate answered 11/8, 2015 at 7:13 Comment(2)
"but it has to be there" - no, it doesn't. The namespace of the Vehicle element in your example isn't http://www.w3.org/2001/XMLSchema-instance - that namespace, within the Vehicles element of your xml, has been associated with the xsd namespace prefix - but no such prefix has been applied to the Vehicle elements within. Therefore, it's in the global namespace instead.Heterothallic
Thanks for the reply, if i leave the namespace out of my model, i get the following error: The specified type was not recognized: name='Model', namespace='', at <Vehicle xmlns=''>. [InvalidOperationException: The specified type was not recognized: name='Model', namespace='', at <Vehicle xmlns=''>.]Satiate
S
7

Please try this:

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 { }

Pay attention to type 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);
}

No need to specify namespace. When serializing an attribute xsi will be added automatically with actual type Model.

xs.Serialize(Console.Out, vehicles);
Save answered 11/8, 2015 at 7:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.