Serialización XML: deshabilita la representación del elemento raíz de la matriz

119

¿Puedo de alguna manera desactivar la representación del elemento raíz de la colección?

Esta clase con atributos de serialización:

[XmlRoot(ElementName="SHOPITEM", Namespace="")]
public class ShopItem
{
    [XmlElement("PRODUCTNAME")]
    public string ProductName { get; set; }       

    [XmlArrayItem("VARIANT")]
    public List<ShopItem> Variants { get; set; }
}

genera este XML:

<SHOPITEM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <PRODUCTNAME>test</PRODUCTNAME>
      <Variants>
          <VARIANT>
              <PRODUCTNAME>hi 1</PRODUCTNAME>
          </VARIANT>
          <VARIANT>
              <PRODUCTNAME>hi 2</PRODUCTNAME>
          </VARIANT>           
      </Variants>        
</SHOPITEM>

No quiero <Variants>elemento aquí. ¿Que debo hacer?

Además, no necesito espacios de nombres xsi y xsd en el elemento raíz ...

Jan Remunda
fuente

Respuestas:

184

Para deshabilitar la representación del elemento raíz de la colección, debe reemplazar el atributo [XmlArrayItem]con [XmlElement]en su código.

Para eliminar los espacios de nombres xsiy xsd, cree una XmlSerializerNamespacesinstancia con un espacio de nombres vacío y páselo cuando necesite serializar su objeto.

Mira este ejemplo:

[XmlRoot("SHOPITEM")]
public class ShopItem
{
    [XmlElement("PRODUCTNAME")]
    public string ProductName { get; set; }

    [XmlElement("VARIANT")] // was [XmlArrayItem]
    public List<ShopItem> Variants { get; set; }
}

// ...

ShopItem item = new ShopItem()
{
    ProductName = "test",
    Variants    = new List<ShopItem>()
    {
        new ShopItem{ ProductName = "hi 1" },
        new ShopItem{ ProductName = "hi 2" }
    }
};

// This will remove the xsi/xsd namespaces from serialization
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");

XmlSerializer ser = new XmlSerializer(typeof(ShopItem));
ser.Serialize(Console.Out, item, ns);  // Inform the XmlSerializerNamespaces here

Tengo esta salida:

<?xml version="1.0" encoding="ibm850"?>
<SHOPITEM>
  <PRODUCTNAME>test</PRODUCTNAME>
  <VARIANT>
    <PRODUCTNAME>hi 1</PRODUCTNAME>
  </VARIANT>
  <VARIANT>
    <PRODUCTNAME>hi 2</PRODUCTNAME>
  </VARIANT>
</SHOPITEM>
Rubens Farias
fuente
Tenga en cuenta que también debe reemplazar [XmlArray]si está presente.
dbc
32

Reemplazar [XmlArrayItem("VARIANT")]con [XmlElement("VARIANT")].

Pent Ploompuu
fuente
1

No creo que sea posible eliminar este elemento utilizando la serialización xml predeterminada (con atributos). Si pudiera hacer esto, la serialización de su ShopItemclase daría como resultado un xml mal formado (sin elemento raíz) para el objeto, lo cual no está permitido.

Sin embargo, lo que puede hacer es implementar manualmente IXmlSerializable. Esto le dará el tipo de control detallado que busca.

[ Editar ] - lo siento - malinterpretó que intentaba eliminar Variantes, no SHOPITEM. Para eliminar el elemento "externo" de la lista, márquelo con un atributo [XmlElement] en lugar de un atributo [XmlArrayItem]. Esto hará que las entradas de la lista solo usen el nombre del elemento especificado, sin envolver la lista en un elemento externo.

Para eliminar los espacios de nombres, esto lo controla el propio seriliazer, no el marcado en la clase. Acabo de notar que aunque actualicé esta respuesta, Rubens Farias proporcionó una respuesta que le muestra cómo eliminar el espacio de nombres.

Rob Levine
fuente
Vaya, leyó mal su publicación, pensó que estaba tratando de eliminar SHOPITEM, ¡solo editando la respuesta!
Rob Levine