Bookmark and Share

Svårighetsgrad
Svårighetsgrad
Betyg (14 röster)
BetygBetygBetygBetygBetyg
 

Serialisering av data till XML

Inledning

Serialisering av data, av engelskans serialize, är ett viktigt begrepp i datorvärlden. Begreppet innebär en översättning av data för att underlätta lagring eller överföring. Data är i detta fall objekt. När sedan datan läses så ska det gå att kunna skapa upp objekten så som de var innan serialiseringen. Den vanligaste formen av serialisering är en översättning till 1'or och 0'or som inte är så lätt att läsa.

I slutet av 90-talet så började behovet av ett standardiserat text-baserat format att öka. XML (Extensible Markup Language) gjorde entré. Detta var ett format som var mer mänskligt läsbart och ej kopplat till något programmeringsspråk. XML har många likheter med HTML och ofta så är faktiskt HTML (xhtml) just XML. Andra populära användningsområden för XML är inom webbutveckling och AJAX där kommunikationen i AJAX använder XML eller det nya word-formatet (.docx) som är XML-baserat. Mer info om XML hittar du här.

I denna artikel ska du få lära dig hur du använder XML i dina program för att enkelt både läsa och spara data. C# har mycket bra stöd för integrering av XML som du strax ska få se. En av de största fördelarna blir att ditt program lättare kan integreras med andra program som vill läsa din data.

Exempel på XML

Vi ska snabbt ta en titt på hur XML kan se ut. Vi börjar med det mest vanliga, nämlihen en HTML sida:

Reglerna för hur XML skrivs är rätt enkla. Varje element (tagg) kan ha ett innehåll, dvs. det som står mellan start- och sluttaggen. Har taggen ingen sluttagg så måste den ändå avslutas med ett /-tecken precis som elementet bok i exemplet nedan. Varje element kan ha ett valfritt antal attribut också, vilka skrivs inne i elementet.

Vi kan också skriva .dtd filer till vår XML som talar om hur datan kan vara lagrad. Vi kan på så sätt specificera vilka attribut som är giltiga på vilka element eller t.ex. vilka element som får innehålla andra element etc etc. Med en dtd-fil kan sedan vår data valideras och vi kan avgöra om en fil följer specifikationerna. I exemplet oxan med XHTML så kan en hänvisning skymta till den dtd som bestämmer vilka regler som gäller för XHTML 1.0.

Vi kommer inte att gå in på hur dtd-filer skrivs eftersom vi inte kommer att använda några i artikeln.

Skapa hjälpklassen ObjectXMLSerializer.cs

Vi kommer att använda oss av en hjälpklass för serialiseringen som avsevärt kommer att underlätta för oss. Den kommer innehålla två stycken publika statiska metoder; ObjectXMLSerializer<T>.Load(path) och ObjectXMLSerializer<T>.Save(object, path). Klassen använder templates för att kunna vara så pass generell så att vi kan använda den till alla sorters klasser. Den går att jämföra med lagringsklassen List<T> som också är skriven som en template.

Hjälpklassen sköter alla detaljer med I/O såsom att skapa läs- och skriv-objekt för filer som kopplas till de metoder för XML-serialisering som .NET erbjuder. Det vi är intresserade av är att kunna spara och ladda data så smidigt som möjligt därför går vi inte in i detalj hur klassen fungerar.

De första testerna

bild

Vi skapar nu några medlemmar i klassen TestKlass samt använder oss av namnutrymmet System.Xml.Serialization. Det enda som vi behöver göra nu för att tala om att klassen ska gå att serialisera är att ange det med ett s.k. attribut på klassdefinitionen. Se koden nedan:

Attributet på rad 4 ska inte förväxlas med alla andra sorters attribut. Med attribut kan man annars mena XML-attribut eller medlemsvariabler till en klass. I detta fall är det en konstruktion med hakparenteser som anger en slags extra information som kan användas under körning. Metoden kallas reflection och är ett mycket kraftfullt sätt att dynamiskt undersöka information om klasser under körning. Vi kommer inte att gå in mer på reflection men du ska veta att det är den tekniken som ligger bakom XML-serialiseringen och dess enkelhet genom att vi bara anger attribut på våra klasser.

En viktigt sak är att klassen som ska serialiseras MÅSTE deklareras som public annars kommer programmet att krascha med ett InvalidOperationException.

Test 1

Dags att se hur det kommer att bli. I vårt huvudprogram skapar vi ett objekt av typen TestKlass och serialiserar den.

Filen test.xml kommer att sparas där din .exe-fil ligger. Vi tar en titt på den.

Vi kan genast konstatera att skyddade (protected) och privata medlemmar i klassen har inte serialiserats. Tyvärr är det så med XML-serialisering att det bara är publika medlemmar och properties som kan serialiseras. Vi kan även konstatera att medlemmarna automatiskt har blivit element med samma namn som variabelnamnet.

Vi testar även att ladda in objektet igen och konstaterar att det fungerar.

bild

Det måste påpekas att klassen som ska de-serialiseras MÅSTE ha en standardkonstruktor. I vårt fall har vi inga konstruktorer alls i TestKlass så en standardkonstruktor kommer att förutsättas trots att vi inte har någon. Finns det ingen standardkonstruktor vid de-serialisering så kommer det att uppstå ett InvalidOperationException när programmet försöker ladda data.

Test 2

Nu är det dags att leka lite med XML-inställningarna. Vi ändrar i TestKlass.

Resultatet blir nu:

Som synes så har vi nu lagt till en massa attribut på klassmedlemmarna. Namn har bytt namn men är fortfarande ett element. Övriga medlemmar har blivit attribut till "föräldranoden", dvs "RootNod". Lägg märke till att du inte behöver ha parenteser på de attribut som du ändå inte tänker skicka med några parametrar (rad 10). Lägg också märke till hur attribut/element med mellanslag i namnet hanteras i XML.

Test 3

Vi testar lite till genom att ändra i TestKlass:

Resultatet i XML blir:

Attributet XmlIgnore förhindrar att publika medlemmar serialiseras. Vi kan även konstatera att vi egentligen inte behöver ange några attribut alls för att en klass ska kunna serialiseras till XML.

Finalen

Vi ska nu titta på hur listor kan användas för att spara ett okänt antal objekt. Vi ska även definiera standardvärden på en del av vår data. Mer om detta senare.

Exemplet kommer att efterlikna en telefonbok så vi börjar med att göra en klass för en Kontakt.

Vi lagrar tre olika saker; förnamn, efternamn och könsroll. Eftersom man kan vara man eller kvinna så passar vi även på att använda en enum för detta. Observera att både klassen och enum'en måste deklareras public. Vidare måste vi även ha en standardkonstruktor. På variabeln Roll sätter vi attributet DefaultValue med värdet Man. DefaultValue kommer från namnutrymmet System.ComponentModel. Med ett standardvärde definierat så behös ej standardmässiga värden serialiseras. På så sätt kan vi få renare och mindre XML.

Vi skriver också en klass för en KontaktBok.

Slutligen skriver vi ett test som först skapar en kontaktbok och några kontakter, sparar den till kontaktbok.xml, läser in den igen och skriver ut alla kontakter.

Resultatet blir:

Avslutning

Jag hoppas att du har fått tillräckliga kunskaper för att börja använda serialisering i C#. Just XML är trevligt då det inte behövs något specialutvecklat program för att ändra datan. Det räcker med en vanlig textredigerare. Du behöver heller inte ägna en massa tid åt att skriva speciell kod för att spara och ladda data.

Vi avslutar med en liten övning. Försök skapa ett program med klasser så att du kan läsa in följande data (nedan) och skriva ut på skärmen:

..

Viktiga begrepp

  • serialize
  • templates
  • reflection

Kommentarer

2 inlägg