Mikuláš je tu! Získaj 90 % extra kreditov ZADARMO s promo kódom CERTIK90 pri nákupe od 1 199 kreditov. Len do nedele 7. 12. 2025! Zisti viac:
NOVINKA: Najžiadanejšie rekvalifikačné kurzy teraz s 50% zľavou + kurz AI ZADARMO. Nečakaj, táto ponuka dlho nevydrží! Zisti viac:

6. diel - Úvod do XML a zápis SAXom v C# .NET

V predchádzajúcom cvičení, Riešené úlohy k 1.-5. lekcii práce so súbormi v C# .NET, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

Dnes sa v kurze C# .NET zameriame na formát XML, najskôr si ho popíšeme, potom si ukážeme triedy, ktoré nám .NET framework poskytuje na jeho čítanie a zápis.

Formát XML

XML (eXtensible Markup Language) je značkovací jazyk vyvinutý organizáciou W3C, ktorá má na starosti webové štandardy. XML je veľmi univerzálny a je podporovaný množstvom jazykov i aplikácií. Slovo extensible (rozšíriteľný) označuje možnosť vytvoriť si pomocou XML vlastný jazyk, tým je napríklad XHTML na tvorbu webových stránok.

XML je jazyk samopopisovací. Má takú štruktúru, že spoznáme, čo ktorá hodnota označuje. Zatiaľ čo v CSV sa môžeme len domnievať, čo je tá tretia osmička, v XML by nám bolo hneď jasné, že je to napríklad počet článkov používateľa. Nevýhodou formátu je samozrejme jeho väčšia veľkosť, čo nám však vo väčšine prípadov nevadí. Osobne takmer vždy pri výbere formátu siaham po XML.

XML sa hodí napríklad na uloženie:

  • konfigurácie programu,
  • hiscore hráčov hry,
  • menšej databázy používateľov.

Vďaka XSD schémam ho môžeme jednoducho zvalidovať a predísť chybám pri behu programu.

XML je možné spracovávať hneď niekoľkými spôsobmi. Zvyčajne jednoduchým kontinuálnym čítaním/zápisom alebo pomocou objektovej štruktúry DOM. Došlo to tak ďaleko, že nám niektoré nástroje vrátane .NET knižníc umožňujú s XML dokumentom pracovať ako s databázou a volať nad ním SQL dopyty. Asi si dokážeme predstaviť, že to uľahčí prácu. Ďalším jazykom na dopytovanie sa nad XML súbormi je napríklad XPath.

XML sa veľmi často používa na výmenu dát medzi rozdielnymi systémami napríklad desktopovou aplikáciou a webovou aplikáciou na serveri. Preto, ako už bolo spomenuté, pre neho existuje mnoho knižníc a každý nástroj ho pozná a vie s ním pracovať. S tým súvisia webové služby, SOAP a podobne, čím sa však teraz nebudeme zaoberať.

Porovnanie formátov XML a CSV

V lekcii Uloženie objektov do CSV v C# .NET - Dokončenie sme si uložili zoznam používateľov do súboru CSV. Ukladali sme meno, vek a dátum registrácie. Hodnoty boli za sebou, oddelené bodkočiarkami. Každý riadok predstavoval jedného používateľa. Obsah súboru vyzeral teda asi takto:

John Smith;22;3/21/2000
James Brown;31;10/30/2012

Nezainteresovaný z toho nič veľmi nespozná, však? Urobme si teraz ekvivalent súboru vo formáte XML:

<?xml version="1.0" encoding="UTF-8" ?>
<users>
    <user age="22">
        <name>John Smith</name>
        <registered>3/21/2000</registered>
    </user>
    <user age="31">
        <name>James Brown</name>
        <registered>10/30/2012</registered>
    </user>
</users>

Teraz každý vidí, čo je v súbore uložené. Vek sme tu uložili ako atribút len preto, aby sme si ukázali, že ho XML vie. Inak by mohol byť ako element spolu s menom a registrovaný. Jednotlivým prvkom sa hovorí elementy. HTML, o ktorom sa dozvieme viac v kurze HTML5 vychádza z rovnakých základov ako XML. Elementy sú väčšinou párové, teda otváracie, potom nasleduje hodnota a uzatváracie s lomkou. Elementy môžu obsahovať ďalšie elementy, štruktúra je teda stromová. Vďaka tomu nie je problém do jediného XML dokumentu uložiť celú hierarchiu objektov.

Na začiatku súboru je XML hlavička. Aby bol dokument validný, musí obsahovať práve jeden koreňový element, tu element používateľa, v ktorom sú zabalené ďalšie elementy. Atribúty sa píšu za názov atribútu do úvodzoviek.

Určite vidíme, že súbor nám nabobtnal, to je daň za to, že vyzerá pekne. Keby nemal používateľ vlastnosti len tri, ale napríklad 30, bolo by vidieť, ako prestáva stačiť CSV formát.

Osobne sa s pribúdajúcimi skúsenosťami stále viac prikláňam k riešeniam, ktoré sú prehľadné a jednoduché, aj keď napríklad zaberajú viac pamäte, a to nielen v súboroch, ale aj v zdrojovom kóde. Nič nie je horšie, ako keď programátor príde za rok k svojmu programu a vôbec nevie, čo je ten ôsmy parameter v CSV, kde je na riadku nejakých 100 čísel. Alebo čo je to päťrozmerné pole, ktoré je síce hrozne rýchle, ale keby si namiesto neho postavil objektovú štruktúru, nemusel by teraz písať program znova.

XML v .NET

Budeme sa tu venovať dvom základným prístupom ku XML:

  • Kontinuálnemu prístupu takzvanému SAX parseru.
  • Objektový prístup (DOM).

Opäť máme v .NET frameworku viac spôsobov, ako s XML pracovať. Niektoré sú zastarané a prítomné len z dôvodu spätnej kompatibility.

Parsovanie XML cez SAX

SAX (Simple API for XML) je vlastne jednoduchá nadstavba čítačky textových súborov. Zápis je pomerne jednoduchý, postupne zapisujeme elementy a atribúty tak, ako idú v súbore za sebou. Stromovú štruktúru tu teda ignorujeme. .NET nám poskytuje triedu XmlWriter, ktorá nás odtieňuje od toho, že je XML textový súbor. Pracujeme iba s elementmi, presnejšie uzlami, viac ďalej.

Čítanie prebieha podobne ako zápis. XML teda čítame ako textový súbor, riadok po riadku, zhora nadol. SAX nám však nedáva riadky, ale postupne takzvané uzly XMLNode, na ktoré pri čítaní postupne naráža. Uzol môže byť element, atribút alebo hodnota. V cykle uzly dostávame tak, ako idú v súbore za sebou. Na čítanie použijeme triedu XmlReader. Obe triedy sú v mennom priestore System.Xml.

Výhodou SAX je vysoká rýchlosť a pamäťová nenáročnosť. Nevýhody spoznáme, až tento prístup ďalej porovnáme s objektovým prístupom DOM.

Zápis XML

Poďme si vytvoriť jednoduché XML. Využijeme na to vyššie uvedený príklad s používateľmi. S triedou User sme pracovali už v predchádzajúcich lekciách, pre istotu si ju tu ešte raz uvedieme. Vytvorme si novú konzolovú aplikáciu XmlSaxWriting a pridajme si triedu User:

class User
{
        public string Name { get; private set; }
        public int Age { get; private set; }
        public DateTime Registered { get; private set; }

        public User(string name, int age, DateTime registered)
        {
                Name = name;
                Age = age;
                Registered = registered;
        }

        public override string ToString()
        {
                return Name;
        }

}
Metóda Main()

Kód budeme pre jednoduchosť písať do metódy Main(), iba si vyskúšame funkčnosť SAXu. Z predchádzajúcich lekcií vieme, ako sa aplikácia píšu správne objektovo.

Do using pridajme System.Xml. XmlWriter vytvárame pomocou továrenskej (statickej) metódy Create(). Ide to aj inak, ale tento spôsob je najvýhodnejší. Objekt bude opäť obalený v bloku using. Do XML môžeme uložiť samozrejme aj len jeden objekt napríklad nastavenie. My si tu ukážeme uloženie zoznamu niekoľkých objektov.

Ako prvý si vytvoríme testovací list používateľov:

List<User> users = new List<User>();
users.Add(new User("John Smith", 22, new DateTime(2000, 3, 21)));
users.Add(new User("James Brown", 31, new DateTime(2016, 10, 30)));
users.Add(new User("Tom Hanks", 16, new DateTime(2011, 1, 12)));

Už máme čo zapisovať. Budeme chcieť, aby bol XML výstup pekne naformátovaný a odsadený podľa svojej stromovej štruktúry. Toto nastavenie bohužiaľ nie je defaultné a preto ho musíme vynútiť odovzdaním inštancie triedy XmlWriterSettings. Tej nastavíme vlastnosť Indent (zanárať) na true:

XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;

Hotovo. Teraz vytvoríme inštanciu triedy XmlWriter pomocou továrenskej metódy Create(). Budeme pracovať v bloku using. Inštancii ako parametre odovzdáme cestu k súboru a nastaveniam:

using (XmlWriter xw = XmlWriter.Create(@"file.xml", settings))
{
}
Zápis dát do súboru

Poďme sa pustiť do samotného zápisu. Najprv zapíšeme hlavičku dokumentu:

xw.WriteStartDocument();

Ďalej, ako už vieme, musí nasledovať koreňový element, v ktorom je celý zvyšok XML obsiahnutý. Na zapisovanie elementov máme metódy WriteStartElement() a WriteEndElement(). Prvá berie v parametri názov elementu, ktorý otvárame. Druhá metóda spozná názov otvoreného elementu sama z kontextu dokumentu a parametre teda nemá. Otvorme koreňový element, v našom prípade element používateľa:

xw.WriteStartElement("users");

Teraz sa dostávame k zápisu jednotlivých používateľov. Ten bude teda prítomný v cykle foreach.

Zápis hodnoty do elementu vykonáme pomocou metódy WriteValue(), parametrom je zapisovaná hodnota. Podobne môžeme elementu pridať atribút metódou WriteAttributeString(), ktorej parametre sú názov atribútu a jeho hodnota. Hodnota je vždy typu string, čiže v našom prípade musíme vek na string previesť. Cyklus a zápis elementu používateľ, zatiaľ ešte bez vnorených elementov, bude teda vyzerať takto:

foreach (User u in users)
{
    xw.WriteStartElement("user");
    xw.WriteAttributeString("age", u.Age.ToString());
    xw.WriteEndElement();
}

Do programu pripíšeme ešte jeden EndElement() na uzavretie koreňového elementu a EndDocument() na ukončenie celého dokumentu. Podobne ako pri textových súboroch musíme aj tu vyprázdniť buffer metódou Flush(). Celý kód programu teda teraz vyzerá takto:

List<User> users = new List<User>();
users.Add(new User("John Smith", 22, new DateTime(2000, 3, 21)));
users.Add(new User("James Brown", 31, new DateTime(2016, 10, 30)));
users.Add(new User("Tom Hanks", 16, new DateTime(2011, 1, 12)));

XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;

using (XmlWriter xw = XmlWriter.Create(@"file.xml", settings))
{
    xw.WriteStartDocument();
    xw.WriteStartElement("users");

    foreach (User u in users)
    {
        xw.WriteStartElement("user");
        xw.WriteAttributeString("age", u.Age.ToString());
        xw.WriteEndElement();
    }

    xw.WriteEndElement();
    xw.WriteEndDocument();
    xw.Flush();
}

Program si skúsime spustiť a uistíme sa, že všetko funguje. Výstup programu vidíme v priečinku s programom na ceste .../bin/debug/file.xml):

<?xml version="1.0" encoding="utf-8"?>
<users>
  <user age="22" />
  <user age="31" />
  <user age="16" />
</users>

Vidíme, že SAX spoznal, že v elemente používateľ nie je okrem atribútu žiadna hodnota a tak tag vyrenderoval ako nepárový. Teraz vložíme do elementu user dva ďalšie elementy, presnejšie jeho vlastnosti meno a dátum registrácie:

xw.WriteStartElement("name");
xw.WriteValue(u.Name);
xw.WriteEndElement();
xw.WriteStartElement("registered");
xw.WriteValue(u.Registered.ToShortDateString());
xw.WriteEndElement();

Ani jeden element v sebe neobsahuje ďalšie elementy ani atribúty. Také elementy iba s textovou hodnotou môžeme zapísať s pomocou jedinej metódy WriteElementString(), ktorej atribúty sú názov elementu a hodnota, ktorú má obsahovať:

xw.WriteElementString("name", u.Name);
xw.WriteElementString("registered", u.Registered.ToShortDateString());

Oba zápisy sú teda ekvivalentné.

Ten kratší vložíme do miesta zápisu elementu user, teda medzi jeho StartElement() a EndElement(). Pre istotu si ešte uveďme kompletný kód časti s cyklom:

foreach (User u in users)
{
    xw.WriteStartElement("user");
    xw.WriteAttributeString("age", u.Age.ToString());

    xw.WriteElementString("name", u.Name);
    xw.WriteElementString("registered", u.Registered.ToShortDateString());

    xw.WriteEndElement();
}

A máme hotovo.

V nasledujúcej lekcii, Čítanie XML SAXom v C# .NET, si načítame XML súbor s niekoľkými používateľmi pomocou SAX parseru. Zo súboru vytvoríme inštancie a pridáme ich do listu.


 

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é 4x (51.79 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Predchádzajúci článok
Riešené úlohy k 1.-5. lekcii práce so súbormi v C# .NET
Všetky články v sekcii
Súbory v C# .NET
Preskočiť článok
(neodporúčame)
Čítanie XML SAXom v C# .NET
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
15 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity