¿Cómo deserializo este documento XML?
<?xml version="1.0" encoding="utf-8"?>
<Cars>
<Car>
<StockNumber>1020</StockNumber>
<Make>Nissan</Make>
<Model>Sentra</Model>
</Car>
<Car>
<StockNumber>1010</StockNumber>
<Make>Toyota</Make>
<Model>Corolla</Model>
</Car>
<Car>
<StockNumber>1111</StockNumber>
<Make>Honda</Make>
<Model>Accord</Model>
</Car>
</Cars>
Tengo esto:
[Serializable()]
public class Car
{
[System.Xml.Serialization.XmlElementAttribute("StockNumber")]
public string StockNumber{ get; set; }
[System.Xml.Serialization.XmlElementAttribute("Make")]
public string Make{ get; set; }
[System.Xml.Serialization.XmlElementAttribute("Model")]
public string Model{ get; set; }
}
.
[System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)]
public class Cars
{
[XmlArrayItem(typeof(Car))]
public Car[] Car { get; set; }
}
.
public class CarSerializer
{
public Cars Deserialize()
{
Cars[] cars = null;
string path = HttpContext.Current.ApplicationInstance.Server.MapPath("~/App_Data/") + "cars.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Cars[]));
StreamReader reader = new StreamReader(path);
reader.ReadToEnd();
cars = (Cars[])serializer.Deserialize(reader);
reader.Close();
return cars;
}
}
que no parecen funcionar :-(
Respuestas:
Aquí hay una versión que funciona. Cambié las
XmlElementAttribute
etiquetas aXmlElement
porque en el xml los valores StockNumber, Make y Model son elementos, no atributos. También eliminé elreader.ReadToEnd();
(esa función lee toda la secuencia y devuelve una cadena, por lo que laDeserialize()
función ya no podía usar el lector ... la posición estaba al final de la secuencia). También me tomé algunas libertades con el nombramiento :).Aquí están las clases:
La función Deserializar:
Y el xml ligeramente modificado (necesitaba agregar un nuevo elemento para envolver <Cars> ... Net es exigente con la deserialización de matrices):
fuente
[Serializable]
es redundante si se usaXmlSerializer
;XmlSerializer
simplemente nunca verifica eso. Del mismo modo, la mayoría de los[Xml...]
atributos son redundantes, ya que simplemente imitan el comportamiento predeterminado; es decir, de forma predeterminada, una propiedad llamadaStockNumber
se almacena como un elemento denominado<StockNumber>
, sin necesidad de atributos para eso.¿Qué tal si solo guarda el xml en un archivo y usa xsd para generar clases de C #?
xsd foo.xml
xsd foo.xsd /classes
Et voila - y un archivo de código C # que debería poder leer los datos a través de
XmlSerializer
:(incluya el foo.cs generado en el proyecto)
fuente
Tienes dos posibilidades.
Método 1. Herramienta XSD
Suponga que tiene su archivo XML en esta ubicación
C:\path\to\xml\file.xml
Puede encontrarlo en
Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools
O si tiene Windows 8 puede comenzar a escribir el símbolo del sistema del desarrollador en la pantalla de iniciocd /D "C:\path\to\xml"
xsd file.xml
xsd /c file.xsd
¡Y eso es! Ha generado clases de C # desde un archivo xml en
C:\path\to\xml\file.cs
Método 2 - Pasta especial
Requiere Visual Studio 2012+
Edit > Paste special > Paste XML As Classes
¡Y eso es!
Uso
El uso es muy simple con esta clase auxiliar:
Todo lo que tienes que hacer ahora es:
fuente
Paste XML As Classes
comando apunta solo a .NET 4.5El siguiente fragmento debería hacer el truco (y puede ignorar la mayoría de los atributos de serialización):
...
fuente
Vea si esto ayuda:
.
Y si no se usa el programa xsd.exe que viene con Visual Studio para crear un documento de esquema basado en ese archivo xml, y luego volver a usarlo para crear una clase basada en el documento de esquema.
fuente
No creo que .net sea 'exigente con la deserialización de matrices'. El primer documento xml no está bien formado. No hay elemento raíz, aunque parece que lo hay. El documento canónico xml tiene una raíz y al menos 1 elemento (si es que lo tiene). En tu ejemplo:
fuente
pruebe este bloque de código si su archivo .xml se ha generado en algún lugar del disco y si ha utilizado
List<T>
:Nota:
C:\serialize.xml
es la ruta de mi archivo .xml. Puede cambiarlo según sus necesidades.fuente
La respuesta de Kevin es buena, aparte del hecho de que, en el mundo real, a menudo no puede modificar el XML original para satisfacer sus necesidades.
También hay una solución simple para el XML original:
Y luego simplemente puede llamar:
fuente
Pruebe esta clase genérica para la serialización y deserialización Xml.
fuente
Para principiantes
Encontré que las respuestas aquí fueron muy útiles, lo que decía que todavía luchaba (solo un poco) para que esto funcionara. Entonces, en caso de que ayude a alguien, explicaré la solución de trabajo:
XML de la pregunta original. El xml está en un archivo Class1.xml,
path
se usa a en este archivo en el código para ubicar este archivo xml.Utilicé la respuesta de @erymski para que esto funcionara, así que creé un archivo llamado Car.cs y agregué lo siguiente:
El otro fragmento de código proporcionado por @erymski ...
... entra en su programa principal (Program.cs),
static CarCollection XCar()
así:Espero eso ayude :-)
fuente
¿Qué tal una clase genérica para deserializar un documento XML?
Esta parte puede o no ser necesaria. Abra el documento XML en Visual Studio, haga clic derecho en el XML, elija propiedades. Luego elija su archivo de esquema.
fuente
Un trazador de líneas:
fuente
La idea es manejar todos los niveles para la deserialización. Vea una solución de muestra que resolvió mi problema similar
El XML anterior se maneja en dos niveles
El nivel interno
De la misma manera que necesita un nivel múltiple con
car as array
Marque este ejemplo para la deserialización multinivelfuente
Si obtiene errores al usar xsd.exe para crear su archivo xsd, use la clase XmlSchemaInference como se menciona en msdn . Aquí hay una prueba unitaria para demostrar:
fuente
Simplemente puede cambiar un atributo para su propiedad de automóvil Cars de XmlArrayItem a XmlElment. Es decir, de
a
fuente
Mi solución:
Edit > Past Special > Paste XML As Classes
para obtener la clase en su códigoList<class1
>), luego use elXmlSerializer
para serializar esa lista en unxml
archivo.deserialize
hacerlo.Código:
NOTA: debe prestar atención al nombre raíz, no lo cambie. El mío es "ArrayOfClass1"
fuente
fuente