Az XML egy gépek és emberek által is olvasható adatformátum, amit az 1990-es évek vége felé szabványosítottak. Számos webes és offline formátum alapja, többek között az RSS, az SVG illetve az Open Office és Office 2007 formátumai is XML alapúak.
Az XML formátumnak serialization esetén a C# programunkban az az előnye, hogy ez egy szabványos formátum, amit jó eséllyel más programozási nyelvekkel, keretrendszerekkel is be lehet olvasni.
Az XML formátum nagy előnye, hogy az osztály, amit szerializálunk, bővíthető marad. Tételezzük fel, hogy van egy osztályunk három tulajdonsággal, majd az osztályt kiírjuk XML formátumba. Ezután még hozzáadunk az osztályhoz két tulajdonságot. Ebben az esetben az eredetileg kiírt XML fájl deszerializálható marad. Az XML által nem tartalmazott tulajdonságok a típusaiknak megfelelő, alapértelmezett értéket fogják felvenni.
Az XML alapú szerializáció hasonlóan működik, mint a bináris. A használatára nézzünk meg egy példát:
using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;
namespace PeldaSerialziationXml
{
[Serializable]
public class Osztaly
{
public int Egesz { get; set; }
public double Tort { get; set; }
public override string ToString()
{
return $"Egesz: {Egesz}, Tort: {Tort}";
}
}
class Program
{
static void Main(string[] args)
{
XmlSerializer serializer = new XmlSerializer(typeof(Osztaly));
using (MemoryStream teszt = new MemoryStream())
{
Osztaly kiirando = new Osztaly
{
Egesz = 42,
Tort = 3.1415
};
Console.WriteLine("Írás előtt:");
Console.WriteLine(kiirando);
serializer.Serialize(teszt, kiirando);
//visszaállunk a stream elejére
//az írás után a végén vagyunk
teszt.Seek(0, SeekOrigin.Begin);
Console.WriteLine("XML adat:\n");
using (var reader = new StreamReader(teszt, Encoding.UTF8, false, 1024, true))
{
Console.WriteLine(reader.ReadToEnd());
}
//visszaállunk ismét a stream elejére
teszt.Seek(0, SeekOrigin.Begin);
Console.WriteLine("\nOlvasás után: ");
Osztaly beolvasott = (Osztaly)serializer.Deserialize(teszt);
Console.WriteLine(beolvasott);
}
Console.ReadKey();
}
}
}
A program kimenete:
Írás előtt:
Egesz: 42, Tort: 3,1415
XML adat:
<?xml version="1.0"?>
<Osztaly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Egesz>42</Egesz>
<Tort>3.1415</Tort>
</Osztaly>
Olvasás után:
Egesz: 42, Tort: 3,1415
A kiírásban és a betöltésben annyi eltérés van, hogy a BinaryFormatter osztály helyett XmlSerializer osztályt példányosítunk. Az XmlSerializer osztály konstruktorának meg kell adni a kiírandó és beolvasandó osztály típusát.
Szintén az osztálynak public módosítóval kell rendelkeznie, kell hogy legyen paraméter nélküli konstruktora és az adattagoknak tulajdonságoknak kell lenniük.
A különbség azonban az, hogy itt a kihagyni kívánt tulajdonságokat nem a NonSerialized attribútummal kell megjelölni, hanem az XmlIgnore attribútummal.
C# osztály XML-ből
Ha van egy kész, más által XML formátumban szolgáltatott adatunk, akkor abból C# osztályt viszonylag könnyen tudunk készíteni a Visual Studio segítségével. Első lépésben vágólapra kell másolnunk az XML fájl tartalmát, majd egy üres .cs fájlt készítenünk. Ez után a Visual Studio ‘Edit’ menüjében találunk egy ‘Paste Special’ menüpontot, aminek egyik almenüje a ‘Paste XML as Classes’ nevet viseli. Erre kattintva az XML adat alapján legenerálódnak a C# osztályok, amelyek az XML beolvasásához és kiírásához kellenek.
Amennyiben régebbi Visual Studio-t használunk, vagy a menüpont nem érhető el, akkor a https://xmltocsharp.azurewebsites.net/ címen található eszköz segítségével ugyanezt meg tudjuk tenni.
Mindkét eszköz esetén érdemes azonban a generált kódot osztályonként szétbontani fájlokra a jobb karbantarthatóság érdekében.
XML és a sebesség
Az XML egy viszonylag komplikált formátum, ezért a beolvasása és kiírása is lassú tud lenni nagy mennyiségű adat esetén. Ez annak köszönhető, hogy a keretrendszer a típus kiíráshoz és beolvasáshoz dinamikusan generálja a beolvasást és kiírást végző kódot. Többek között ezért szükséges az XmlSerializer példányosításánál a típus információ.
A sebesség problémaként nagy mennyiségű adatnál, illetve sok írásnál, olvasásnál jelentkezhet.
A probléma áthidalható .NET Framework esetén, ha már fordítási időben kigeneráljuk az XML beolvasó és kiíró kódot. Ez nem jár kódolással részünkről, csak annyival, hogy módosítani kell a fordítási beállításokat.
A projekt ‘Properties’ ablakját előhozva a ‘Build’ fülön legalul van egy ‘Generate serialization assembly’ pont, aminek alapértelmezett ‘Auto’ az értéke. Ha ezt módosítjuk ‘On’ állapotra, akkor a porogramunk mellé létrejön még egy DLL fájl, ami a kigenerált XML kezelő kódot fogja tartalmazni.
Ha ez fordítási időben kimaradna, akkor az SGEN program segítségével bármikor le tudjuk gyártani a programunkhoz. Az SGEN eszköz a .NET SDK része, ami a Visual Studio-val együtt települ. A Developer Command Prompt-ból tudjuk használni, ami a Visual Studio telepítésünk mellett a Start menüben található.
Az SGEN használata igen egyszerű. A lefordított program binárisát kell neki paraméternek megadni, illetve minden olyan DLL fájlt a programunkból, ami XML-hez tartozó osztályokat tartalmaz. A fenti példaprogramhoz tartozó optimalizált XML kezeléshez az alábbi parancsot futtattam le:
sgen pelda_serialziation_xml.exe