XML Serialization - Nonaktifkan rendering elemen root dari array

119

Dapatkah saya menonaktifkan rendering elemen root dari koleksi?

Kelas ini dengan atribut serialisasi:

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

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

menghasilkan XML ini:

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

Saya tidak ingin <Variants>elemen di sini. Apa yang harus saya lakukan?

Juga saya tidak membutuhkan ruang nama xsi dan xsd di elemen root ...

Jan Remunda
sumber

Jawaban:

184

Untuk menonaktifkan rendering elemen root koleksi, Anda harus mengganti atribut [XmlArrayItem]dengan [XmlElement]di kode Anda.

Untuk menghapus ruang nama xsidan xsd, buat XmlSerializerNamespacesinstance dengan namespace kosong dan teruskan saat Anda perlu membuat serial objek.

Lihat contoh ini:

[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

Saya mendapatkan hasil ini:

<?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
sumber
Perhatikan bahwa Anda juga harus mengganti [XmlArray]jika ada.
dbc
32

Ganti [XmlArrayItem("VARIANT")]dengan [XmlElement("VARIANT")].

Pent Ploompuu
sumber
1

Saya tidak percaya adalah mungkin untuk menghapus elemen ini menggunakan serialisasi xml default (dengan atribut). Jika Anda bisa melakukan ini, maka membuat serial ShopItemkelas Anda akan menghasilkan format xml yang buruk (tidak ada elemen root) untuk objek tersebut, yang tidak diizinkan.

Namun, yang dapat Anda lakukan adalah menerapkan secara manual IXmlSerializable. Ini akan memberi Anda jenis kontrol yang sangat baik yang Anda inginkan.

[ Sunting ] - maaf - salah membaca bahwa Anda mencoba menghapus Varian, bukan SHOPITEM. Untuk menghapus elemen "luar" Daftar, cukup tandai dengan atribut [XmlElement] daripada atribut [XmlArrayItem]. Ini akan menyebabkan entri daftar hanya menggunakan nama elemen yang ditentukan, tanpa membungkus daftar di elemen luar.

Untuk menghapus namespace, ini dikontrol oleh seriliazer itu sendiri, bukan markup di kelas. Saya baru saja memperhatikan bahwa sementara saya memperbarui jawaban ini, Rubens Farias telah memberikan balasan yang menunjukkan kepada Anda cara menghilangkan namespace.

Rob Levine
sumber
Ups - salah membaca posting Anda - mengira Anda mencoba menghapus SHOPITEM - hanya mengedit jawaban!
Rob Levine