Exportar (0) Imprimir
Expandir todo

XmlSerializer (Clase)

Actualización: noviembre 2007

Serializa y deserializa objetos en y desde documentos XML. XmlSerializer permite controlar el modo en que se codifican los objetos en XML.

Espacio de nombres:  System.Xml.Serialization
Ensamblado:  System.Xml (en System.Xml.dll)

public class XmlSerializer
public class XmlSerializer
public class XmlSerializer

La serialización XML es el proceso mediante el cual los campos y propiedades públicos de un campo se convierten a un formato de serie (en este caso, XML) a efectos de almacenamiento o transporte. La deserialización vuelve a crear el objeto en su estado original a partir de los resultados XML. La serialización puede considerarse como una manera de guardar el estado de un objeto en una secuencia o un búfer. Por ejemplo, ASP.Net utiliza la clase XmlSerializer para codificar mensajes de servicios Web XML.

Los datos de los objetos se describen utilizando construcciones de lenguaje de programación como, por ejemplo, clases, campos, propiedades, tipos primitivos, matrices e incluso XML incrustado en forma de objetos XmlElement o XmlAttribute. Existe la opción de crear clases propias, anotadas con atributos, o de utilizar Herramienta Definición de esquemas XML (Xsd.exe) para generar las clases de acuerdo con un documento de definición de esquema XML (XSD) existente. Si se dispone de un esquema XML, es posible ejecutar Xsd.exe con el fin de generar un conjunto de clases con establecimiento inflexible de tipos para el esquema y que se anoten con atributos para ajustarse al esquema cuando se proceda a la serialización.

Para transferir datos entre los objetos y XML es necesaria una asignación de las construcciones del lenguaje de programación al esquema XML y viceversa. XmlSerializer y las herramientas relacionadas como Xsd.exe constituyen el puente entre estas dos tecnologías tanto en tiempo de diseño como en tiempo de ejecución. En tiempo de diseño, utilice Xsd.exe para generar un documento de esquema XML (.xsd) a partir de las clases personalizadas o para generar clases a partir de un esquema determinado. En ambos casos, las clases se anotan con atributos personalizados para instruir a XmlSerializer cómo debe realizar las asignaciones entre el sistema de esquemas XML y Common Language Runtime. En tiempo de ejecución, las instancias de las clases se pueden serializar en documentos XML que siguen el esquema dado. De manera similar, estos documentos XML se pueden deserializar en objetos en tiempo de ejecución. Observe que el esquema XML es opcional y no es necesario en tiempo de diseño ni en tiempo de ejecución.

Controlar el código XML generado

Para controlar el código XML generado, se pueden aplicar atributos especiales a clases y miembros. Por ejemplo, para especificar un nombre diferente de elemento XML, hay que aplicar un XmlElementAttribute a un campo o propiedad públicos y establecer la propiedad ElementName. Para obtener una lista completa de atributos similares, vea Atributos que controlan la serialización XML. También puede implementar la interfaz IXmlSerializable para controlar el resultado XML.

Si el código XML generado se ajusta a la sección 5 del documento "Simple Object Access Protocol (SOAP) 1.1" del Consorcio WWC (), debe construirse el XmlSerializer con un XmlTypeMapping. Para controlar el SOAP XML codificado, use uno de los atributos que aparecen en Atributos que controlan la serialización SOAP codificada.

XmlSerializer permite obtener ventajas del manejo de clases con establecimiento inflexible de tipos y seguir aprovechando la flexibilidad de XML. Al utilizar campos o propiedades de tipo XmlElement, XmlAttribute o XmlNode en las clases con establecimiento inflexible de tipos, se pueden leer partes del documento XML directamente en objetos XML.

Si se trabaja con esquemas XML ampliables, también se pueden utilizar los atributos XmlAnyElementAttribute y XmlAnyAttributeAttribute para serializar y deserializar elementos o atributos que no se encuentren en el esquema original. Para utilizar los objetos, aplique XmlAnyElementAttribute a un campo que devuelva una matriz de objetos XmlElement o aplique XmlAnyAttributeAttribute a un campo que devuelva una matriz de objetos XmlAttribute.

Si una propiedad o un campo devuelve un objeto complejo como, por ejemplo, una matriz o una instancia de clase, XmlSerializer lo convierte a un elemento anidado en el documento XML principal. Por ejemplo, la primera clase del código siguiente devuelve una instancia de la segunda clase.

public class MyClass
{
    public MyObject MyObjectProperty;
}
public class MyObject
{
    public string ObjectName;
}

El resultado XML serializado tiene el siguiente aspecto:

<MyClass>
  <MyObjectProperty>
  <ObjectName>My String</ObjectName>
  </MyObjectProperty>
</MyClass>

Si un esquema incluye un elemento opcional (minOccurs = '0') o un valor predeterminado, existen dos opciones. Una opción es utilizar System.ComponentModel.DefaultValueAttribute para especificar el valor predeterminado, como se muestra en el código siguiente.

public class PurchaseOrder
{
    [System.ComponentModel.DefaultValueAttribute ("2002")]
    public string Year;
}

La otra opción consiste en usar un modelo especial para crear un campo booleano reconocido por XmlSerializer y aplicar XmlIgnoreAttribute al campo. El modelo se crea con el formato propertyNameSpecified. Por ejemplo, si hay un campo denominado "MyFirstName", deberá crear asimismo un campo denominado "MyFirstNameSpecified" que indique al XmlSerializer si debe generar el elemento XML denominado "MyFirstName". El ejemplo siguiente muestra esta opción.

public class OptionalOrder
{
    // This field should not be serialized 
    // if it is uninitialized.
    public string FirstOrder;

    // Use the XmlIgnoreAttribute to ignore the 
    // special field named "FirstOrderSpecified".
    [System.Xml.Serialization.XmlIgnoreAttribute]
    public bool FirstOrderSpecified;
}

Reemplazar la serialización predeterminada

También se puede reemplazar la serialización de cualquier conjunto de objetos, así como sus campos y propiedades, creando uno de los atributos apropiados y agregándolo a una instancia de la clase XmlAttributes. Este tipo de reemplazo de la serialización permite, en primer lugar, controlar y aumentar la serialización de los objetos detectados en una DLL, incluso si no se tiene acceso al origen; en segundo lugar, permite crear un conjunto de clases serializables y, sin embargo, serializar los objetos de varias maneras. Para obtener información, vea la clase XmlAttributeOverrides y Cómo: Controlar la serialización de clases derivadas.

Para serializar un objeto, llame al método Serialize. Para deserializar un objeto, llame al método Deserialize.

Para agregar espacios de nombres XML a un documento XML, vea XmlSerializerNamespaces.

swxzdhc0.alert_note(es-es,VS.90).gifNota:

XmlSerializer da un trato especial a las clases que implementan IEnumerable o ICollection. Una clase que implementa IEnumerable debe implementar un método Add público que requiere un solo parámetro. El parámetro del método Add debe ser del mismo tipo que el que devuelve la propiedad Current en el valor devuelto de GetEnumerator, o una de las bases de dicho tipo. Una clase que implementa ICollection (como, por ejemplo, CollectionBase) además de IEnumerable debe tener una propiedad Item indizada y pública (indizador en C#) que toma un entero y debe tener una propiedad Count pública de tipo entero. El parámetro del método Add debe ser del mismo tipo que el que devuelve la propiedad Item o una de las bases de dicho tipo. Para las clases que implementan ICollection, los valores que se han de serializar se recuperan de la propiedad Item indizada y no llamando a GetEnumerator.

Debe tener permiso para escribir en el directorio temporal (definido por la variable de entorno TEMP) con el fin de deserializar un objeto.

Ensamblados generados dinámicamente

Para mejorar el rendimiento, la infraestructura de serialización XML genera los ensamblados dinámicamente para serializar y deserializar los tipos especificados. La infraestructura encuentra y reutiliza dichos ensamblados. Este comportamiento sólo se produce al utilizar los constructores siguientes:

XmlSerializer.XmlSerializer(Type)

XmlSerializer.XmlSerializer(Type, String)

Si utiliza cualquier otro constructor, se generan varias versiones del mismo ensamblado que no se descargan nunca, lo que produce una pérdida de memoria y reducción del rendimiento. La solución más fácil es usar uno de los dos constructores previamente mencionados. De lo contrario, debe almacenar en la caché los ensamblados de Hashtable, como se muestra en el ejemplo siguiente.

Hashtable serializers = new Hashtable();

// Use the constructor that takes a type and XmlRootAttribute.
XmlSerializer s = new XmlSerializer(typeof(MyClass), myRoot);

// Implement a method named GenerateKey that creates unique keys 
// for each instance of the XmlSerializer. The code should take 
// into account all parameters passed to the XmlSerializer 
// constructor.
object key = GenerateKey(typeof(MyClass), myRoot);

// Check the local cache for a matching serializer.
XmlSerializer ser = (XmlSerializer)serializers[key];
if (ser == null) 
{
    ser = new XmlSerializer(typeof(MyClass), myRoot);
    // Cache the serializer.
    serializers[key] = ser;
}
else
{
    // Use the serializer to serialize, or deserialize.
}

Serialización de ArrayList y lista genérica

XmlSerializer no puede serializar o deserializar lo siguiente:

Serialización de enumeraciones de tipo largo sin signo

No se pueden crear instancias de XmlSerializer para serializar una enumeración si se cumplen las siguientes condiciones: la enumeración es del tipo largo sin signo (ulong en C#) y contiene cualquier miembro con un valor mayor que 9.223.372.036.854.775.807. Por ejemplo, no se puede serializar.

public enum LargeNumbers: ulong
{
    a = 9223372036854775808
}
// At runtime, the following code will fail.
xmlSerializer mySerializer=new XmlSerializer(typeof(LargeNumbers));

Los objetos marcados con el atributo Obsolete ya no se serializan

En .NET Framework 3.5 la clase XmlSerializer ya no serializa objetos marcados como [Obsolete].

En el siguiente ejemplo, hay dos clases principales: PurchaseOrder y Test. La clase PurchaseOrder contiene información sobre una sola compra. La clase Test contiene los métodos que crean la orden de compra y leen la orden de compra creada.

using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

/* The XmlRootAttribute allows you to set an alternate name 
   (PurchaseOrder) of the XML element, the element namespace; by 
   default, the XmlSerializer uses the class name. The attribute 
   also allows you to set the XML namespace for the element.  Lastly,
   the attribute sets the IsNullable property, which specifies whether 
   the xsi:null attribute appears if the class instance is set to 
   a null reference. */
[XmlRootAttribute("PurchaseOrder", Namespace="http://www.cpandl.com", 
IsNullable = false)]
public class PurchaseOrder
{
   public Address ShipTo;
   public string OrderDate; 
   /* The XmlArrayAttribute changes the XML element name
    from the default of "OrderedItems" to "Items". */
   [XmlArrayAttribute("Items")]
   public OrderedItem[] OrderedItems;
   public decimal SubTotal;
   public decimal ShipCost;
   public decimal TotalCost;   
}

public class Address
{
   /* The XmlAttribute instructs the XmlSerializer to serialize the Name
      field as an XML attribute instead of an XML element (the default
      behavior). */
   [XmlAttribute]
   public string Name;
   public string Line1;

   /* Setting the IsNullable property to false instructs the 
      XmlSerializer that the XML attribute will not appear if 
      the City field is set to a null reference. */
   [XmlElementAttribute(IsNullable = false)]
   public string City;
   public string State;
   public string Zip;
}

public class OrderedItem
{
   public string ItemName;
   public string Description;
   public decimal UnitPrice;
   public int Quantity;
   public decimal LineTotal;

   /* Calculate is a custom method that calculates the price per item,
      and stores the value in a field. */
   public void Calculate()
   {
      LineTotal = UnitPrice * Quantity;
   }
}

public class Test
{
   public static void Main()
   {
      // Read and write purchase orders.
      Test t = new Test();
      t.CreatePO("po.xml");
      t.ReadPO("po.xml");
   }

   private void CreatePO(string filename)
   {
      // Create an instance of the XmlSerializer class;
      // specify the type of object to serialize.
      XmlSerializer serializer = 
      new XmlSerializer(typeof(PurchaseOrder));
      TextWriter writer = new StreamWriter(filename);
      PurchaseOrder po=new PurchaseOrder();

      // Create an address to ship and bill to.
      Address billAddress = new Address();
      billAddress.Name = "Teresa Atkinson";
      billAddress.Line1 = "1 Main St.";
      billAddress.City = "AnyTown";
      billAddress.State = "WA";
      billAddress.Zip = "00000";
      // Set ShipTo and BillTo to the same addressee.
      po.ShipTo = billAddress;
      po.OrderDate = System.DateTime.Now.ToLongDateString();

      // Create an OrderedItem object.
      OrderedItem i1 = new OrderedItem();
      i1.ItemName = "Widget S";
      i1.Description = "Small widget";
      i1.UnitPrice = (decimal) 5.23;
      i1.Quantity = 3;
      i1.Calculate();

      // Insert the item into the array.
      OrderedItem [] items = {i1};
      po.OrderedItems = items;
      // Calculate the total cost.
      decimal subTotal = new decimal();
      foreach(OrderedItem oi in items)
      {
         subTotal += oi.LineTotal;
      }
      po.SubTotal = subTotal;
      po.ShipCost = (decimal) 12.51; 
      po.TotalCost = po.SubTotal + po.ShipCost; 
      // Serialize the purchase order, and close the TextWriter.
      serializer.Serialize(writer, po);
      writer.Close();
   }

   protected void ReadPO(string filename)
   {
      // Create an instance of the XmlSerializer class;
      // specify the type of object to be deserialized.
      XmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder));
      /* If the XML document has been altered with unknown 
      nodes or attributes, handle them with the 
      UnknownNode and UnknownAttribute events.*/
      serializer.UnknownNode+= new 
      XmlNodeEventHandler(serializer_UnknownNode);
      serializer.UnknownAttribute+= new 
      XmlAttributeEventHandler(serializer_UnknownAttribute);

      // A FileStream is needed to read the XML document.
      FileStream fs = new FileStream(filename, FileMode.Open);
      // Declare an object variable of the type to be deserialized.
      PurchaseOrder po;
      /* Use the Deserialize method to restore the object's state with
      data from the XML document. */
      po = (PurchaseOrder) serializer.Deserialize(fs);
      // Read the order date.
      Console.WriteLine ("OrderDate: " + po.OrderDate);

      // Read the shipping address.
      Address shipTo = po.ShipTo;
      ReadAddress(shipTo, "Ship To:");
      // Read the list of ordered items.
      OrderedItem [] items = po.OrderedItems;
      Console.WriteLine("Items to be shipped:");
      foreach(OrderedItem oi in items)
      {
         Console.WriteLine("\t"+
         oi.ItemName + "\t" + 
         oi.Description + "\t" +
         oi.UnitPrice + "\t" +
         oi.Quantity + "\t" +
         oi.LineTotal);
      }
      // Read the subtotal, shipping cost, and total cost.
      Console.WriteLine("\t\t\t\t\t Subtotal\t" + po.SubTotal);
      Console.WriteLine("\t\t\t\t\t Shipping\t" + po.ShipCost); 
      Console.WriteLine("\t\t\t\t\t Total\t\t" + po.TotalCost);
   }

   protected void ReadAddress(Address a, string label)
   {
      // Read the fields of the Address object.
      Console.WriteLine(label);
      Console.WriteLine("\t"+ a.Name );
      Console.WriteLine("\t" + a.Line1);
      Console.WriteLine("\t" + a.City);
      Console.WriteLine("\t" + a.State);
      Console.WriteLine("\t" + a.Zip );
      Console.WriteLine();
   }

   private void serializer_UnknownNode
   (object sender, XmlNodeEventArgs e)
   {
      Console.WriteLine("Unknown Node:" +   e.Name + "\t" + e.Text);
   }

   private void serializer_UnknownAttribute
   (object sender, XmlAttributeEventArgs e)
   {
      System.Xml.XmlAttribute attr = e.Attr;
      Console.WriteLine("Unknown attribute " + 
      attr.Name + "='" + attr.Value + "'");
   }
}


import System.*;
import System.Xml.*;
import System.Xml.Serialization.*;
import System.IO.*;

/* The XmlRootAttribute allows you to set an alternate name 
   (PurchaseOrder) of the XML element, the element namespace; by 
   default, the XmlSerializer uses the class name. The attribute 
   also allows you to set the XML namespace for the element.  Lastly,
   the attribute sets the IsNullable property, which specifies whether 
   the xsi:null attribute appears if the class instance is set to 
   a null reference. */
/** @attribute XmlRootAttribute("PurchaseOrder",
    Namespace = "http://www.cpandl.com", IsNullable = false)
 */
public class PurchaseOrder
{
    public Address shipTo;
    public String orderDate;
    /* The XmlArrayAttribute changes the XML element name
       from the default of "OrderedItems" to "Items". */
    /** @attribute XmlArrayAttribute("Items")
     */
    public OrderedItem orderedItems[];
    public System.Decimal subTotal;
    public System.Decimal shipCost;
    public System.Decimal totalCost;
} //PurchaseOrder

public class Address
{
    /* The XmlAttribute instructs the XmlSerializer to serialize the Name
       field as an XML attribute instead of an XML element (the default
       behavior). */
    /** @attribute XmlAttribute()
     */
    public String name;
    public String line1;

    /* Setting the IsNullable property to false instructs the 
       XmlSerializer that the XML attribute will not appear if 
       the City field is set to a null reference. */
    /** @attribute XmlElementAttribute(IsNullable = false)
     */
    public String city;
    public String state;
    public String zip;
} //Address

public class OrderedItem
{
    public String itemName;
    public String description;
    public System.Decimal unitPrice;
    public int quantity;
    public System.Decimal lineTotal;

    /* Calculate is a custom method that calculates the price per item,
       and stores the value in a field. */
    public void Calculate()
    {
        lineTotal = Decimal.Multiply(unitPrice, Convert.ToDecimal(quantity));
    } //Calculate
} //OrderedItem

public class Test
{
    public static void main(String[] args)
    {
        // Read and write purchase orders.
        Test t = new Test();
        t.CreatePO("po.xml");
        t.ReadPO("po.xml");
    } //main

    private void CreatePO(String fileName)
    {
        // Create an instance of the XmlSerializer class;
        // specify the type of object to serialize.
        XmlSerializer serializer =
            new XmlSerializer(PurchaseOrder.class.ToType());
        TextWriter writer = new StreamWriter(fileName);
        PurchaseOrder po = new PurchaseOrder();

        // Create an address to ship and bill to.
        Address billAddress = new Address();
        billAddress.name = "Teresa Atkinson";
        billAddress.line1 = "1 Main St.";
        billAddress.city = "AnyTown";
        billAddress.state = "WA";
        billAddress.zip = "00000";

        // Set ShipTo and BillTo to the same addressee.
        po.shipTo = billAddress;
        po.orderDate = System.DateTime.get_Now().ToLongDateString();

        // Create an OrderedItem object.
        OrderedItem i1 = new OrderedItem();
        i1.itemName = "Widget S";
        i1.description = "Small widget";
        i1.unitPrice = Convert.ToDecimal(5.23);
        i1.quantity = 3;
        i1.Calculate();

        // Insert the item into the array.
        OrderedItem items[] = { i1 };
        po.orderedItems = items;

        // Calculate the total cost.
        System.Decimal subTotal = new System.Decimal();
        for (int iCtr = 0; iCtr < items.length; iCtr++) {
            OrderedItem oi = items[iCtr];
            subTotal = Decimal.Add(subTotal, oi.lineTotal);
        }

        po.subTotal = subTotal;
        po.shipCost = Convert.ToDecimal(12.51);
        po.totalCost = Decimal.Add(po.subTotal, po.shipCost);

        // Serialize the purchase order, and close the TextWriter.
        serializer.Serialize(writer, po);
        writer.Close();
    } //CreatePO

    protected void ReadPO(String fileName)
    {
        // Create an instance of the XmlSerializer class;
        // specify the type of object to be deserialized.
        XmlSerializer serializer =
            new XmlSerializer(PurchaseOrder.class.ToType());
        /* If the XML document has been altered with unknown 
           nodes or attributes, handle them with the 
           UnknownNode and UnknownAttribute events.*/
        serializer.add_UnknownNode(
            new XmlNodeEventHandler(Serializer_UnknownNode));
        serializer.add_UnknownAttribute(
            new XmlAttributeEventHandler(Serializer_UnknownAttribute));

        // A FileStream is needed to read the XML document.
        FileStream fs = new FileStream(fileName, FileMode.Open);

        // Declare an object variable of the type to be deserialized.
        PurchaseOrder po;

        /* Use the Deserialize method to restore the object's state with
           data from the XML document. */
        po = (PurchaseOrder)serializer.Deserialize(fs);

        // Read the order date.
        Console.WriteLine("OrderDate: " + po.orderDate);

        // Read the shipping address.
        Address shipTo = po.shipTo;
        ReadAddress(shipTo, "Ship To:");

        // Read the list of ordered items.
        OrderedItem items[] = po.orderedItems;
        Console.WriteLine("Items to be shipped:");
        for (int iCtr = 0; iCtr < items.length; iCtr++) {
            OrderedItem oi = items[iCtr];
            Console.WriteLine("\t" + oi.itemName + "\t"
                + oi.description + "\t" + oi.unitPrice + "\t"
                + oi.quantity + "\t" + oi.lineTotal);
        }
        // Read the subtotal, shipping cost, and total cost.
        Console.WriteLine("\t\t\t\t\t Subtotal\t" + po.subTotal);
        Console.WriteLine("\t\t\t\t\t Shipping\t" + po.shipCost);
        Console.WriteLine("\t\t\t\t\t Total\t\t" + po.totalCost);
    } //ReadPO

    protected void ReadAddress(Address a, String label)
    {
        // Read the fields of the Address object.
        Console.WriteLine(label);
        Console.WriteLine("\t" + a.name);
        Console.WriteLine("\t" + a.line1);
        Console.WriteLine("\t" + a.city);
        Console.WriteLine("\t" + a.state);
        Console.WriteLine("\t" + a.zip);
        Console.WriteLine();
    } //ReadAddress

    private void Serializer_UnknownNode(Object sender, XmlNodeEventArgs e)
    {
        Console.WriteLine("Unknown Node:" + e.get_Name() + "\t" + e.get_Text());
    } //Serializer_UnknownNode

    private void Serializer_UnknownAttribute(Object sender,
        XmlAttributeEventArgs e)
    {
        System.Xml.XmlAttribute attr = e.get_Attr();
        Console.WriteLine("Unknown attribute " + attr.get_Name() + "='"
            + attr.get_Value() + "'");
    } //Serializer_UnknownAttribute
} //Test


System.Object
  System.Xml.Serialization.XmlSerializer

Este tipo es seguro para la ejecución de subprocesos.

Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98, Windows CE, Windows Mobile para Smartphone, Windows Mobile para Pocket PC, Xbox 360

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

.NET Framework

Compatible con: 3.5, 3.0, 2.0, 1.1, 1.0

.NET Compact Framework

Compatible con: 3.5, 2.0

XNA Framework

Compatible con: 2.0, 1.0

Adiciones de comunidad

AGREGAR
Mostrar:
© 2015 Microsoft