7. diel - Čítanie XML Saxe v VB.NET
V minulom dieli nášho seriálu tutoriálov o VB.NET, Úvod do XML a zápis Saxe , sme si predstavili formát XML a ukázali si, ako pomocou SAXUM vytvoriť jednoduché XML.
Teraz na minulý diel nadviažeme a napíšeme si proces opačný, teda načítanie XML súboru s používateľmi a zostavenie príslušnej objektovej štruktúry (listu užívateľov).
Pre úplnosť si opäť uvedieme náš XML súbor soubor.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="31"> <jmeno>Jan Novák</jmeno> <registrovan>30.10.2012</registrovan> </uzivatel> <uzivatel vek="16"> <jmeno>Tomáš Marný</jmeno> <registrovan>12.1.2011</registrovan> </uzivatel> </uzivatele>
A naši triedu Uzivatel.vb:
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.Registrovan = registrovan End Sub Public Overrides Function ToString() As String Return Me.Jmeno End Function End Class
Založme si nový projekt, pôjde opäť o konzolovú aplikáciu. Pomenujeme ju XmlSaxCteni a do zložky bin / debug nakopírujeme náš XML súbor. K projektu pripojíme tiež triedu Uzivatel. Užívateľa budeme chcieť načítať do nejakej kolekcie, vytvorme si teda prázdny hárok uzivatele. Kód budeme kvôli jednoduchosti písať do metódy Main, ako to urobiť dobre objektovo sme si v tejto sekcii už ukazovali.
Dim uzivatele As New List(Of Uzivatel)
Čítanie XML cez SAX
Na čítanie XML cez SAX nám .NET framework poskytuje triedu XmlReader. Poďme si vytvoriť jej inštanciu. Ako tomu bolo pri triede XmlWriter, aj tu na to využijeme továrenské metódy Create, ktorej parametrom je názov súboru. Nezabudneme do Imports pripísať System.Xml. Všetko bude v bloku using, ktorý sa nám postará o uzavretí súboru:
Using xr As XmlReader = XmlReader.Create("soubor.xml") End Using
Pripravíme si pomocné premenné pre vlastnosti používateľa. Nemôžeme ukladať priamo do inštancie, pretože vlastnosti sú read-only. Druhou možnosťou môže byť povoliť modifikáciu zvonka, tým ale strácame časť zapuzdrenie. Vlastnosti naplníme východiskovými hodnotami, tie sa dosadí v prípade, že daná hodnota nebude v XML zapísaná. Budeme potrebovať niekam ukladať meno aktuálneho elementu, k tomu si zadefinujeme stringové premennú element. Kód píšeme pochopiteľne do using bloku.
Dim jmeno As String = "" Dim vek As Integer = 0 Dim registrovan As DateTime = DateTime.Now Dim element As String = ""
Začneme načítať súbor. XmlReader načíta súbor riadok po riadku, zhora nadol. Na jeho inštanciu voláme metódu Read. Tá nám pri každom zavolaní načíta ďalšia tzv. Uzol. Uzlom môže byť element, prípadne atribút alebo textová hodnota elementu (nás bude zaujímať Element, Text a EndElement), ďalším typom uzla môže byť napr. Komentár, ktoré pre nás teraz nebudú dôležité. Ak je čítačka na konci súboru, vráti metóda read false, v opačnom prípade vracia true. Postúpime teda k postupnému načítanie všetkých uzlov v dokumente pomocou while cyklu:
While xr.Read() End While
Na inštanciu XmlReader máme niekoľko užitočných vlastností, budeme používať NodeType, v ktorej je uložený typ aktuálneho uzla, na ktorom sa čítačka nachádza. Ďalej použijeme vlastnosti Name a Value, v ktorých je uložené meno aktuálneho uzla a jeho hodnota (ak nejakú má).
Nás budú teraz zaujímať 2 typy uzlov, Element a Text. Poďme na ne reagovať, zatiaľ napíšeme prázdne podmienky:
If xr.NodeType = XmlNodeType.Element Then End If
Teraz vložíme kód do prvej podmienky. Budeme teda reagovať na načítanie elementu. Je tu potreba vykonať 2 akcie.
Kľúčovou akciou bude uloženie názvu elementu do premennej element. Tak budeme vzápätí schopní v druhej podmienke zistiť, ktorého elementu je text, ktorý práve čítame.
Zakaždým, keď narazíme na element uzivatel, načítame atribút vek pomocou metódy GetAttribute (), ktorej parametrom je názov atribútu. Atribút aktuálneho elementu možné načítať takto jednoducho. S hodnotou to tak jednoduché nie je, síce existujú metódy ReadContentAsTyp, ale pozor, tých z nevysvetliteľného dôvodu vykonajú Read a tak rozbijú beh while cyklu. V nezanořených XML by čítačka nefungovala správne. Nejakú dobu som sa snažil problém vyriešiť, ale riešenie bola natoľko krkolomná, že som došiel k záveru ReadContentAs vôbec nepoužívať. Obsah prvej podmienky teda bude vyzerať takto:
If xr.NodeType = XmlNodeType.Element Then element = xr.Name If element = "uzivatel" Then vek = xr.GetAttribute("vek") End If ElseIf xr.NodeType = XmlNodeType.Text Then End If
Prejdime do ďalšej vetvy, teda do spracovania hodnoty elementu. Tu využijeme vopred uložené hodnoty názvu elementu, ktorú si vložíme do Select Case. Podľa elementu uložíme hodnotu do danej vlastnosti užívateľa:
Select Case element Case "jmeno" jmeno = xr.Value Case "registrovan" registrovan = DateTime.Parse(xr.Value) End Select
Už sme veľmi blízko, bystrejší si iste všimli, že používateľa nikde nepridávame. Jeho pridanie nastane vo chvíli načítanie uzatváracieho elementu uzivatel. K našim dvom podmienkam teda pridáme tretí:
' načítáme konec elementu ElseIf xr.NodeType = XmlNodeType.EndElement And xr.Name = "uzivatel" Then uzivatele.Add(New Uzivatel(jmeno, vek, registrovan))
máme hotovo
Pre istotu prikladám kompletnú kód načítanie súboru:
Using xr As XmlReader = XmlReader.Create("soubor.xml") Dim jmeno As String = "" Dim vek As Integer = 0 Dim registrovan As DateTime = DateTime.Now Dim element As String = "" While xr.Read() If xr.NodeType = XmlNodeType.Element Then element = xr.Name If element = "uzivatel" Then vek = xr.GetAttribute("vek") End If ElseIf xr.NodeType = XmlNodeType.Text Then Select Case element Case "jmeno" jmeno = xr.Value Case "registrovan" registrovan = DateTime.Parse(xr.Value) End Select ElseIf xr.NodeType = XmlNodeType.EndElement And xr.Name = "uzivatel" Then uzivatele.Add(New Uzivatel(jmeno, vek, registrovan)) End If End While End Using
Zostáva užívateľa vypísať, aby sme vedeli, že sme ich načítali správne. Upravíme si metódu toString () v triede Uzivatel tak, aby vypisovala všetky hodnoty:
Public Overrides Function ToString() As String Return String.Format("{0}, {1}, {2}", Jmeno, Vek, Registrovan.ToShortDateString()) End Function
Užívateľa jednoducho vypíšeme:
' výpis načtených objektů For Each u As Uzivatel In uzivatele Console.WriteLine(u) Next Console.ReadKey()
a výsledok:
Ak sa vám načítanie príliš nepáčilo, dám vám za pravdu. Kým generovanie nového XML súboru je Saxe veľmi jednoduché a prirodzené, načítanie je naozaj krkolomné.
Nabudúce, Práca s XML súbory pomocou DOM vo VB.NET , sa pozrieme na DOM, teda objektový prístup k XML dokumentu.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 166x (67.87 kB)
Aplikácia je vrátane zdrojových kódov v jazyku VB