Serialização XML - Desativa a renderização do elemento raiz da matriz

119

Posso desativar a renderização do elemento raiz da coleção?

Esta classe com atributos de serialização:

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

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

gera 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>

Eu não quero <Variants>elemento aqui. O que devo fazer?

Além disso, não preciso de namespaces xsi e xsd no elemento raiz ...

Jan Remunda
fonte

Respostas:

184

Para desativar a renderização do elemento raiz da coleção, você deve substituir o atributo [XmlArrayItem]por [XmlElement]em seu código.

Para remover os namespaces xsie xsd, crie uma XmlSerializerNamespacesinstância com um namespace vazio e passe-o quando precisar serializar seu objeto.

Dê uma olhada neste exemplo:

[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

Eu tenho esta saída:

<?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
fonte
Observe que você também deve substituir, [XmlArray]se houver.
dbc
32

Substitua [XmlArrayItem("VARIANT")]por [XmlElement("VARIANT")].

Pent Ploompuu
fonte
1

Não acredito que seja possível remover este elemento usando a serialização xml padrão (com atributos). Se você pudesse fazer isso, serializar sua ShopItemclasse resultaria em xml mal formado (sem elemento raiz) para o objeto, o que não é permitido.

O que você pode fazer, no entanto, é implementar manualmente IXmlSerializable. Isso lhe dará o tipo de controle refinado que você procura.

[ Editar ] - desculpe - interpretou mal que você estava tentando remover Variants, não SHOPITEM. Para remover o elemento "externo" da Lista, basta marcá-lo com um atributo [XmlElement] em vez de um atributo [XmlArrayItem]. Isso fará com que as entradas da lista usem apenas o nome do elemento especificado, sem envolver a lista em um elemento externo.

Para remover os namespaces, isso é controlado pelo próprio seriliazer, não pela marcação na classe. Acabei de notar que, embora tenha atualizado esta resposta, Rubens Farias forneceu uma resposta que mostra como eliminar o namespace.

Rob Levine
fonte
opa - interpretou mal sua postagem - pensei que você estava tentando remover SHOPITEM - apenas editando a resposta!
Rob Levine