2015-08-11 9 views
7

Sto tentando di deserializzare un po 'di XML e non riesco a far funzionare lo spazio dei nomi/xsi:type="Model". Se xsi:type="Model" viene lasciato fuori dall'XML funziona, ma deve essere lì. Se lascio il namespace fuori dal mio modello, ottengo un errore, se lo rinominano, ottengo una lista vuota.Deserializing xml, compreso lo spazio dei nomi

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> 

Modello

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

} 

deserializzazione

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

L'esempio precedente restituisce un empt y lista, perché lo spazio dei nomi è sbagliato, per quanto ne so - come faccio a ottenere una lista vera e propria?

EDIT Non ho alcun controllo sul XML, sto ottenendo che da un fornitore diverso, quindi dovrò cambiare il resto del codice di conseguenza.

+2

"ma deve essere lì" - no, non è così. Lo spazio dei nomi dell'elemento 'Vehicle' nel tuo esempio non è' http: // www.w3.org/2001/XMLSchema-instance' - che lo spazio dei nomi, all'interno dell'elemento 'Vehicles' del tuo xml, è stato associato al 'xsd' prefisso dello spazio dei nomi - ma nessun prefisso di questo tipo è stato applicato agli elementi' Veicolo' all'interno. Pertanto, è invece nello spazio dei nomi globale. –

+0

Grazie per la risposta, se lascio il namespace fuori dal mio modello, ottengo il seguente errore: Il tipo specificato non è stato riconosciuto: name = 'Model', namespace = '', a . [InvalidOperationException: il tipo specificato non è stato riconosciuto: name = 'Model', namespace = '', a .] – forte

risposta

5

Si prega di provare questo:

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

Prestare attenzione al tipo 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); 
} 

Non è necessario specificare lo spazio dei nomi. Quando si serializza un attributo xsi verrà aggiunto automaticamente con il tipo effettivo Model.

xs.Serialize(Console.Out, vehicles); 
+0

Funziona come un incantesimo, grazie! :) – forte