Do nového roku jako lepší programátoři? Znovu otevíráme večerní školu programování. Nette framework, návrhové vzory, testování nebo vůbec poprvé kurzy ASP.NET dostupné odkudkoli v republice.

6. díl - Úvod do XML a zápis SAXem

Ostatní jazyky Visual Basic .NET Práce se soubory Úvod do XML a zápis SAXem

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulém dílu našeho seriálu tutoriálů o VB.NET jsme si napsali databázi pomocí textových souborů, přesněji souborů ve formátu CSV. Dnes se zaměříme na formát XML, nejprve si ho popíšeme, poté si ukážeme třídy, které nám .NET framework poskytuje k jeho čtení a zápisu. Zápis si vyzkoušíme dnes, čtení příště.

Formát XML

Nyní vás zahrnu spoustou pojmů, když něčemu nebudete rozumět, vůbec to navadí, vše si tu ještě probereme :)

XML (eXtensible Markup Language) je značkovací jazyk, který vyvinulo W3C (organizace, která má na starosti webové standardy). XML je velmi univerzální a je podporováno řadou jazyků i aplikací. Slovo extensible (rozšiřitelný) označuje možnost vytvořit si pomocí XML vlastní jazyk, tím je např. XHTML pro tvorbu webových stránek. XML je jazyk samopopisovací, má takovou strukturu, že poznáme, co která hodnota označuje. Zatímco v CSV se můžeme jen domnívat, co je ta třetí osmička, v XML by nám bylo hned jasné, že je to počet článků uživatele (například). Nevýhodou formátu je samozřejmě jeho větší velikost, což nám však ve většině případů nevadí. Osobně téměř vždy při výběru formátu sahám po XML, hodí se např. k uložení konfigurace programu, hiscore hráčů hry nebo k menší databázi uživatelů. Díky XSD schématům ho můžeme jednoduše zvalidovat a předejít chybám při běhu programu.

XML je možné zpracovávat hned několika způsoby. Obvykle jednoduchým kontinuálním čtením/zápisem nebo pomocí objektové struktury DOM. Došlo to tak daleko, že nám některé nástroje (včetně .NET) umožňují s XML dokumentem pracovat jako s databází a volat nad ním SQL dotazy. Asi si dokážete představit, že to usnadní práci. Dalším jazykem k dotazování se nad XML soubory je např. XPath.

XML konkuruje jednodušší, ale méně prosazený JSON. Ten narozdíl od XML umožňuje snadné logování na konec souboru bez načtení celého dokumentu.

XML se velmi často používá k výměně dat mezi rozdílnými systémy (např. desktopovou aplikací a webovou aplikací na serveru), proto jak již bylo zmíněno existuje pro něj mnoho knihoven a každý nástroj ho zná a umí s ním pracovat. S tím souvisejí webové služby, SOAP a podobně, čímž se však nyní nebudeme zabývat.

Minule jsme si uložili seznam uživatelů do souboru CSV. Ukládalo se jméno, věk a datum registrace. Hodnoty byly zasebou, oddělené středníky. Každý řádek představoval jednoho uživatele. Obsah souboru vypadal tedy asi takto:

Pavel Slavík;22;21.3.2000
Jan Novák;31;30.10.2012

Nezasvěcený z toho nic moc nepozná, že? Udělejme si nyní ekvivalent souboru ve formátu XML:

<?xml version="1.0" encoding="UTF-8" ?>
<uzivatele>
        <uzivatel vek="22">
                <jmeno>Pavel Slavík</jmeno>
                <registrovan>21.3.2000</registrovan>
        </uzivatel>
        <uzivatel vek="22">
                <jmeno>Jan Novák</jmeno>
                <registrovan>30.10.2012</registrovan>
        </uzivatel>
</uzivatele>

Nyní každý vidí, co je v souboru uloženo. Věk jsem zde uložil jako atribut jen proto, abych ukázal, že je XML umí, jinak by mohl být jako element spolu se jménem a registrován. Nyní jsem tedy vyzradil, že jednotlivým prvkům se říká elementy. Ty určitě všichni znáte z HTML, které vychází ze stejných základů jako XML. Elementy jsou většinou párové, tedy otevírací, poté následuje hodnota a uzavírací s lomítkem. Elementy mohou obsahovat další elementy, struktura je tedy stromová. Díky tomu není problém do jediného XML dokumentu uložit celou hierarchii objektů. Na začátku souboru je XML hlavička. Aby byl dokument validní, musí obsahovat právě 1 kořenový element, zde element uzivatele, ve kterém jsou zabaleny další elementy. Atributy se píší za název atributu do uvozovek.

Určitě vidíme, že soubor nám nabobtnal, to je daň za to, že vypadá hezky. Kdyby neměl uživatel atributy jen 3, ale např. 30, bylo by vidět, jak CSV formát přestává stačit. Osobně se s přibývajícími zkušenostmi stále více přikláním k řešením, která jsou přehledná a jednoduchá, i když třeba zabírají více paměti (a to nejen v souborech, ale i ve zdrojovém kódu). Nic není horšího, než když programátor přijde za rok ke svému programu a vůbec neví, co je ten osmý parametr v CSV, kde je na řádku 100 nějakých čísel. Nebo co je to pětirozměrné pole, které je sice hrozně rychlé, ale kdyby si místo něj postavil objektovou strukturu, nemusel by nyní psát program odznovu. Ale to jsem odbočil.

XML v .NET

Budeme se zde věnovat dvou základním přístupům ke XML. Kontinuálnímu přístupu (tzv. SAX parser) a přístupu objektovému (DOM). Dnešní a příští díl je věnovám SAXu, další DOMu. Opět máme v .NET frameworku více způsobů, jak s XML pracovat, některé jsou zastaralé a přítomné jen z důvodu zpětné kompatibility. Strávil jsem nad XML poměrně dost času, abych sem sepsal jen ty aktuální a jednoduché konstrukce.

Parsování XML přes SAX

SAX (jako Simple API for XML) je vlastně jednoduchá nadstavba čtečky textových souborů. Zápis je poměrně jednoduchý, postupně zapisujeme elementy a atributy tak, jak jdou v souboru zasebou. Stromovou strukturu zde tedy ignorujeme. .NET nám poskytuje třídu XmlWriter, která nás odstiňuje od toho, že je XML textový soubor. Pracujeme pouze s elementy (přesněji uzly, více dále).

Čtení probíhá podobně, jako zápis. XML tedy čteme jako textový soubor, řádek po řádku, odshora dolů. SAX nám však nedává řádky, ale postupně tzv. uzly (XMLNode), na které při čtení postupně naráží. Uzel může být element, atribut nebo hodnota. V cyklu uzly dostáváme tak, jak jdou v souboru zasebou. Ke čtení použijeme třídu XmlReader. Obě třídy jsou ve jmenném prostoru System.Xml.

Výhodou SAX je vysoká rychlost a paměťová nenáročnost. Nevýhody poznáme, až tento přístup srovnáme s objektovým přístupem DOM.

Zápis XML

Pojďme si vytvořit jednoduché XML, využijeme k tomu výše uvedený příklad s uživateli. S třídou Uzivatel jsme pracovali již minule, pro jistotu ji zde ještě jednou přiložím. Vytvořte si nový projekt - konzolovou aplikaci jménem XmlSaxZapis a třídu k projektu přidejte:

Public Class Uzivatel
        Private _jmeno As String
        Public Property Jmeno As String
                Get
                        Return _jmeno
                End Get
                Private Set(ByVal value As String)
                        _jmeno = value
                End Set
        End Property

        Private _vek As Integer
        Public Property Vek As Integer
                Get
                        Return _vek
                End Get
                Set(ByVal value As Integer)
                        _vek = value
                End Set
        End Property

        Private _registrovan As DateTime
        Public Property Registrovan As DateTime
                Get
                        Return _registrovan
                End Get
                Set(ByVal value As DateTime)
                        _registrovan = value
                End Set
        End Property

        Public Sub New(jmeno As String, vek As Integer, registrovan As DateTime)
                Me.Jmeno = jmeno
                Me.Vek = vek
                Me.Registrrovan = registrovan
        End Sub

        Public Overrides Function ToString() As String
                Return Me.Jmeno
        End Function
End Class

Kód budeme pro jednoduchost psát do metody Main, pouze si vyzkoušíme funkčnost SAXu. Z minulých dílů víte, jak se aplikace píší správně objektově.

Do Imports přidejme System.Xml. XmlWriter vytváříme pomocí tovární (statické) metody Create. Jde to i jinak, ale tento způsob je nejvýhodnější. Objekt bude opět obalen v bloku using. Do XML můžeme uložit samozřejmě i jen 1 objekt (např. nastavení), my si zde ukážeme uložení seznamu několika objektů. Pokud budete chtít uložit objekt jen jeden, bude úprava již hračkou :)

Jako první si vytvoříme testovací list uživatelů:

Dim uzivatele As New List(Of Uzivatel)
uzivatele.Add(New Uzivatel("Pavel Slavík", 22, New DateTime(2000, 3, 21)))
uzivatele.Add(New Uzivatel("Jan Novák", 31, New DateTime(2012, 10, 30)))
uzivatele.Add(New Uzivatel("Tomáš Marný", 16, New DateTime(2011, 1, 12)))

Již máme co zapisovat. Budeme chtít, aby byl XML výstup hezky naformátovaný a odsazený dle stromové struktury. Toto nastavení bohužel není defaultní a proto ho musíme vynutit předáním instance třídy XmlWriterSettings. Té nastavíme vlastnost Indent (zanořovat) na true:

Dim nastaveni As New XmlWriterSettings()
nastaveni.Indent = True

Hotovo. Nyní vytvoříme instanci třídy XmlWriter pomocí tovární metody Create. Budeme pracovat v bloku using. Instanci jako parametry předáme cestu k souboru a nastavení:

Using xw As XmlWriter = XmlWriter.Create("soubor.txt", nastaveni)

End Using

Pojďme se pustit do samotného zápisu. Nejprve zapíšeme hlavičku dokumentu:

xw.WriteStartDocument()

Dále (jak již víme) musí následovat kořenový element, ve kterém je celý zbytek XML obsažen. K zapisování elementů máme metody WriteStartElement a WriteEndElement. První bere v atributu název elementu, který otevíráme. Druhá metoda pozná název otevřeného elementu sama z kontextu dokumentu a parametry tedy nemá. Otevřme kořenový element, v našem případě element uzivatele:

xw.WriteStartElement("uzivatele")

Nyní se dostáváme k zápisu jednotlivých uživatelů, ten bude tedy přítomen ve foreach cyklu.

Zápis hodnoty do elementu provedeme pomocí metody WriteValue, parametrem je zapisovaná hodnota. Obdobně můžeme elementu přidat atribut metodou WriteAttributeS­tring, jejíž parametry jsou název atributu a jeho hodnota. Hodnota je vždy typu String. Cyklus a zápis elementu uživatel (zatím ještě bez vnořených elementů) bude tedy vypadat takto:

For Each u As Uzivatel In uzivatele
        xw.WriteStartElement("uzivatel")
        xw.WriteAttributeString("vek", u.Vek)
        xw.WriteEndElement()
Next

Do programu připíšeme ještě jeden EndElement k uzavření kořenového elementu a EndDocument k ukončení celého dokumentu. Podobně jako u textových souborů musíme i zde vyprázdnit buffer metodou Flush. Celý kód programu tedy nyní vypadá takto:

'testovací kolekce uživatelů
Dim uzivatele As New List(Of Uzivatel)
uzivatele.Add(New Uzivatel("Pavel Slavík", 22, New DateTime(2000, 3, 21)))
uzivatele.Add(New Uzivatel("Jan Novák", 31, New DateTime(2012, 10, 30)))
uzivatele.Add(New Uzivatel("Tomáš Marný", 16, New DateTime(2011, 1, 12)))

'nastavení XmlWriteru
Dim nastaveni As New XmlWriterSettings()
nastaveni.Indent = True

'zápis uživatelů
Using xw As XmlWriter = XmlWriter.Create("soubor.xml", nastaveni)
        xw.WriteStartDocument() 'hlavička
        xw.WriteStartElement("uzivatele") 'otevření kořenového elementu uzivatele

        'zápis jednotlivých uživatelů
        For Each u As Uzivatel In uzivatele
                xw.WriteStartElement("uzivatel")
                xw.WriteAttributeString("vek", u.Vek)
                xw.WriteEndElement()
        Next

        xw.WriteEndElement() 'uzavření koncového elementu
        xw.WriteEndDocument() 'konec dokumentu
        xw.Flush()
End Using

Program si zkusíme spustit a ujistíme se, že vše funguje. Výstup programu by měl vypadat takto (složka s programem/bin/de­bug/soubor.xml):

<?xml version="1.0" encoding="utf-8"?>
<uzivatele>
  <uzivatel vek="22" />
  <uzivatel vek="31" />
  <uzivatel vek="16" />
</uzivatele>

Vidíme, že SAX poznal, že v elementu uzivatel není kromě atributu žádná hodnota a tak tag vyrenderoval jako nepárový. Nyní vložíme do elementu uzivatel 2 další elementy, přesněji jeho vlastnosti jméno a datum registrace:

xw.WriteStartElement("jmeno")
xw.WriteValue(u.Jmeno)
xw.WriteEndElement()
xw.WriteStartElement("registrovan")
xw.WriteValue(u.Registrovan.ToShortDateString())
xw.WriteEndElement()

Ani jeden element v sobě neobsahuje další elementy ani atributy. Takového elementy pouze s textovou hodnotou můžeme zapsat s pomocí jediné metody WriteElementString, jejíž atributy jsou název elementu a hodnota, kterou má obsahovat:

xw.WriteElementString("jmeno", u.Jmeno)
xw.WriteElementString("registrovan", u.Registrovan.ToShortDateString())

Oba zápisy jsou tedy ekvivalentní.

Ten kratší vložíme do místa zápisu elementu uzivatel, tedy mezi jeho StartElement a EndElement. Pro jistotu si ještě uveďme kompletní kód části s cyklem:

For Each u As Uzivatel In uzivatele
        xw.WriteStartElement("uzivatel")
        xw.WriteAttributeString("vek", u.Vek)

        xw.WriteStartElement("jmeno")
        xw.WriteValue(u.Jmeno)

        xw.WriteStartElement("registrovan")
        xw.WriteValue(u.Registrovan.ToShortDateString())
        xw.WriteEndElement()
Next

A máme hotovo. Hotový program je jako vždy ke stažení pod článkem. Příště budeme přes SAX XML číst.


 

Stáhnout

Staženo 176x (64.78 kB)
Aplikace je včetně zdrojových kódů v jazyce VB

 

  Aktivity (1)

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.

Jak se ti líbí článek?
Celkem (2 hlasů) :
55555


 


Miniatura
Všechny články v sekci
Práce se soubory v Visual Basic .NET
Miniatura
Následující článek
Čtení XML SAXem v VB.NET

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!