Serialización XML de .NET
-
09-06-2019 - |
Pregunta
Estoy trabajando en un conjunto de clases que se utilizarán para serializar en XML.El XML no lo controlo yo y está bastante bien organizado.Desafortunadamente, hay varios conjuntos de nodos anidados, el propósito de algunos de ellos es simplemente contener una colección de sus hijos.Según mi conocimiento actual de serialización XML, esos nodos requieren otra clase.
¿Hay alguna manera de hacer que una clase se serialice en un conjunto de nodos XML en lugar de solo uno?Como siento que estoy siendo tan claro como el barro, digamos que tenemos el xml:
<root>
<users>
<user id="">
<firstname />
<lastname />
...
</user>
<user id="">
<firstname />
<lastname />
...
</user>
</users>
<groups>
<group id="" groupname="">
<userid />
<userid />
</group>
<group id="" groupname="">
<userid />
<userid />
</group>
</groups>
</root>
Lo ideal sería 3 clases.Una clase root
con colecciones de user
y group
objetos.Sin embargo, lo mejor que puedo entender es que necesito una clase para root
, users
, user
, groups
y group
, dónde users
y groups
contienen sólo colecciones de user
y group
respectivamente, y root
contiene una users
, y groups
objeto.
¿Alguien por ahí que sepa mejor que yo?(no mientas, sé que las hay).
Solución
¿No estás usando el XmlSerializador?Es bastante bueno y hace que hacer cosas como esta sea realmente fácil (¡lo uso bastante!).
Simplemente puede decorar las propiedades de su clase con algunos atributos y el resto estará hecho por usted.
¿Ha considerado utilizar XmlSerializer o hay alguna razón particular por la que no?
Aquí hay un fragmento de código de todo el trabajo necesario para serializar lo anterior (en ambos sentidos):
[XmlArray("users"),
XmlArrayItem("user")]
public List<User> Users
{
get { return _users; }
}
Otros consejos
Sólo necesitaría tener los Usuarios definidos como una matriz de objetos de Usuario.XmlSerializer lo renderizará adecuadamente.
Vea este enlace para ver un ejemplo:http://www.informit.com/articles/article.aspx?p=23105&seqNum=4
Además, recomendaría usar Visual Studio para generar un XSD y usar la utilidad de línea de comandos XSD.EXE para mostrarle la jerarquía de clases, según http://quickstart.developerfusion.co.uk/quickstart/howto/doc/xmlserialization/XSDToCls.aspx
Escribí esta clase en el pasado para hacer lo que creo que es similar a lo que estás tratando de hacer.Utilizaría métodos de esta clase en objetos que desee serializar en XML.Por ejemplo, dado un empleado...
utilizando Utilidades;usando System.Xml.Serialization;
Xmlroot ("empleado")] empleado de clase pública {private string name = "steve";
[XmlElement("Name")]
public string Name { get { return name; } set{ name = value; } }
public static void Main(String[] args)
{
Employee e = new Employee();
XmlObjectSerializer.Save("c:\steve.xml", e);
}
}
este código debería generar:
<Employee>
<Name>Steve</Name>
</Employee>
El tipo de objeto (Empleado) debe ser serializable.Pruebe [Serializable (verdadero)].Tengo una versión mejor de este código en alguna parte, estaba aprendiendo cuando lo escribí.De todos modos, consulte el código a continuación.Lo estoy usando en algún proyecto, así que definitivamente funciona.
using System;
using System.IO;
using System.Xml.Serialization;
namespace Utilities
{
/// <summary>
/// Opens and Saves objects to Xml
/// </summary>
/// <projectIndependent>True</projectIndependent>
public static class XmlObjectSerializer
{
/// <summary>
/// Serializes and saves data contained in obj to an XML file located at filePath <para></para>
/// </summary>
/// <param name="filePath">The file path to save to</param>
/// <param name="obj">The object to save</param>
/// <exception cref="System.IO.IOException">Thrown if an error occurs while saving the object. See inner exception for details</exception>
public static void Save(String filePath, Object obj)
{
// allows access to the file
StreamWriter oWriter = null;
try
{
// Open a stream to the file path
oWriter = new StreamWriter(filePath);
// Create a serializer for the object's type
XmlSerializer oSerializer = new XmlSerializer(obj.GetType());
// Serialize the object and write to the file
oSerializer.Serialize(oWriter.BaseStream, obj);
}
catch (Exception ex)
{
// throw any errors as IO exceptions
throw new IOException("An error occurred while saving the object", ex);
}
finally
{
// if a stream is open
if (oWriter != null)
{
// close it
oWriter.Close();
}
}
}
/// <summary>
/// Deserializes saved object data of type T in an XML file
/// located at filePath
/// </summary>
/// <typeparam name="T">Type of object to deserialize</typeparam>
/// <param name="filePath">The path to open the object from</param>
/// <returns>An object representing the file or the default value for type T</returns>
/// <exception cref="System.IO.IOException">Thrown if the file could not be opened. See inner exception for details</exception>
public static T Open<T>(String filePath)
{
// gets access to the file
StreamReader oReader = null;
// the deserialized data
Object data;
try
{
// Open a stream to the file
oReader = new StreamReader(filePath);
// Create a deserializer for the object's type
XmlSerializer oDeserializer = new XmlSerializer(typeof(T));
// Deserialize the data and store it
data = oDeserializer.Deserialize(oReader.BaseStream);
//
// Return the deserialized object
// don't cast it if it's null
// will be null if open failed
//
if (data != null)
{
return (T)data;
}
else
{
return default(T);
}
}
catch (Exception ex)
{
// throw error
throw new IOException("An error occurred while opening the file", ex);
}
finally
{
// Close the stream
oReader.Close();
}
}
}
}