Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

7. diel - Zápis XML súborov Saxe v Jave

V minulom dieli nášho seriálu tutoriálov pre Javu sme si popísali formát XML. Dnes si v Jave taký súbor vytvoríme pomocou prístupu SAX.

Zápis XML

Poďme si vytvoriť jednoduché XML, využijeme na to minule uvedený príklad s užívateľmi. Vytvorte si nový projekt menom XmlSaxZapis ak projektu pridajte nasledujúci triedu:

public class Uzivatel {
    private String jmeno;
    private int vek;
    private LocalDate registrovan;
    public static DateTimeFormatter formatData = DateTimeFormatter.ofPattern("d'.'MMMM yyyy H:mm");

    public Uzivatel(String jmeno, int vek, LocalDate registrovan){
        this.jmeno = jmeno;
        this.vek = vek;
        this.registrovan = registrovan;
    }

    @Override
    public String toString() {
           return getJmeno();
    }

    public String getJmeno() {
        return jmeno;
    }

    public int getVek() {
        return vek;
    }

    public LocalDate getRegistrovan() {
        return registrovan;
    }
}

Kód budeme pre jednoduchosť písať do metódy main (), len si vyskúšame funkčnosť SAXUM. Z minulých dielov viete, ako sa aplikácia píšu správne objektovo.

XMLStreamWriter vytvárame pomocou triedy XMLOutputFactory. Do XML môžeme uložiť samozrejme i len 1 objekt (napr. Nastavenie), my si tu ukážeme uloženie zoznamu niekoľkých objektov. Ak budete chcieť uložiť objekt len jeden, bude úprava už hračkou :)

Ako prvý si vytvoríme testovací ArrayList užívateľov:

ArrayList<Uzivatel> uzivatele = new ArrayList<>();
LocalDate datum1 = LocalDate.of(2000, Month.MARCH, 21);
LocalDate datum2 = LocalDate.of(2012, Month.OCTOBER, 30);
LocalDate datum3 = LocalDate.of(2011, Month.JANUARY, 1);
uzivatele.add(new Uzivatel("Pavel Slavík", 22, datum1));
uzivatele.add(new Uzivatel("Jan Novák", 31, datum2));
uzivatele.add(new Uzivatel("Tomáš Marný", 16, datum3));

Teraz vytvoríme inštanciu triedy XMLStreamWriter pomocou XMLOutputFactory, tá samotná sa vytvára továrenské metódou newInstance (). Bohužiaľ nemôžeme použiť blok try-with-resources, pretože ho XMLStreamWriter nepodporuje. Inštanciu ako parameter odovzdáme FileWriter, ako tomu bolo u textových súborov.

XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter xsw = null;
try{
    xsw = xof.createXMLStreamWriter(new FileWriter("soubor.xml"));
}
catch (Exception e){
        System.err.println("Chyba při zápisu: " + e.getMessage());
}
finally{
    try{
        if (xsw != null){
                xsw.close();
        }
    }
    catch (Exception e){
            System.err.println("Chyba při uzavírání souboru: " + e.getMessage());
    }
}

Kód je kvôli nemožnosti použiť try-with-resources trochu krkolomný, neskôr si ukážeme aj ďalšie prístupy ku XML dokumentu.

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

xsw.writeStartDocument();

Ďalej (ako už vieme) musí nasledovať koreňový element, v ktorom je celý zvyšok XML obsiahnutý. K zapisovanie elementov máme metódy writeStartElement() a writeEndElement(). Prvý berie v atribúte 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 uzivatele:

xsw.writeStartElement("uzivatele");

Teraz sa dostávame k zápisu jednotlivých užívateľov, ten bude teda prítomný vo foreach cyklu.

Zápis hodnoty do elementu prevedieme pomocou metódy writeCharacters(), parametrom je zapisovaná hodnota. Obdobne môžeme elementu pridať atribút metódou writeAttribute(), 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 užívateľ (zatiaľ ešte bez vnorených elementov) bude teda vyzerať takto:

for (Uzivatel u : uzivatele)
{
    xsw.writeStartElement("uzivatel");
    xsw.writeAttribute("vek", Integer.toString(u.getVek()));
    xsw.writeEndElement();
}

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

// testovací kolekce uživatelů
ArrayList<Uzivatel> uzivatele = new ArrayList<>();
LocalDate datum1 = LocalDate.of(2000, Month.MARCH, 21);
LocalDate datum2 = LocalDate.of(2012, Month.OCTOBER, 30);
LocalDate datum3 = LocalDate.of(2011, Month.JANUARY, 1);
uzivatele.add(new Uzivatel("Pavel Slavík", 22, datum1));
uzivatele.add(new Uzivatel("Jan Novák", 31, datum2));
uzivatele.add(new Uzivatel("Tomáš Marný", 16, datum3));

// Zápis uživatelů
XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter xsw = null;
try {
    xsw = xof.createXMLStreamWriter(new FileWriter("soubor.xml"));
    xsw.writeStartDocument();
    xsw.writeStartElement("uzivatele");

    for (Uzivatel u : uzivatele) {
        xsw.writeStartElement("uzivatel");
        xsw.writeAttribute("vek", Integer.toString(u.getVek()));
        xsw.writeEndElement();
    }

    xsw.writeEndElement();
    xsw.writeEndDocument();
    xsw.flush();
}
catch (Exception e) {
        System.err.println("Chyba při zápisu: " + e.getMessage());
}
finally {
    try {
        if (xsw != null) {
                xsw.close();
        }
    }
    catch (Exception e) {
            System.err.println("Chyba při uzavírání souboru: " + e.getMessage());
    }
}

Program si skúsime spustiť a uistíme sa, že všetko funguje. Výstup programu by mal vyzerať takto (zložka s projektom / soubor.xml):

<?xml version="1.0" ?><uzivatele><uzivatel vek="22"></uzivatel><uzivatel vek="31"></uzivatel><uzivatel vek="16"</uzivatel></uzivatele>

Dáta vyzerajú v poriadku, ale formátovanie nie je žiadne. Poďme to napraviť. Pod hlavné metódu main() vytvoríme novú metódu, ktorú nazveme formatuj(String soubor). Tá bude v parametri prijímať cestu k súboru, ktorý má naformátovať.

private static void formatuj(String soubor) {
    // TODO sem napíšeme tělo formátovače
}

Do tela metódy pridáme nasledujúce riadky:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new InputStreamReader(new FileInputStream(soubor))));

// Získáme novou instanci transformeru
Transformer xformer = TransformerFactory.newInstance().newTransformer();
// Nastavíme formátování pro XML
xformer.setOutputProperty(OutputKeys.METHOD, "xml");
// Nastavíme odsazení
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
Source source = new DOMSource(document);
Result result = new StreamResult(new File(soubor));
xformer.transform(source, result);

Výsledný sformátovaný zápis by mal vyzerať takto:

<?xml version="1.0" ?>
<uzivatele>
  <uzivatel vek="22"></uzivatel>
  <uzivatel vek="31"></uzivatel>
  <uzivatel vek="16"></uzivatel>
</uzivatele>

Vidíme, že SAX spoznal, že v elemente uzivatel nie je okrem atribútu žiadna hodnota a tak tag vyrenderoval ako nepárový. Teraz vložíme do elementu uzivatel 2 ďalšie elementy, presnejšie jeho atribúty meno a dátum registrácie. K tomu účelu si na triede Uzivatel vytvorme ešte statický DateTimeFormatter:

public static DateTimeFormatter formatData = DateTimeFormatter.ofPattern("d'.'MMMM yyyy H:mm");

Statika je tu dôvodná, je to pomocný formátovač pre prácu s atribútom triedy, ktorý sa hodí sprístupniť aj zvonku.

A kód zápisu v cykle sa rozrastie o:

xsw.writeStartElement("jmeno");
xsw.writeCharacters(u.getJmeno());
xsw.writeEndElement();
xsw.writeStartElement("registrovan");
xsw.writeCharacters(Uzivatel.formatData.format(u.getRegistrovan()));
xsw.writeEndElement();

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

for (Uzivatel u : uzivatele) {
    xsw.writeStartElement("uzivatel");
    xsw.writeAttribute("vek", Integer.toString(u.getVek()));
    xsw.writeStartElement("jmeno");
    xsw.writeCharacters(u.getJmeno());
    xsw.writeEndElement();
    xsw.writeStartElement("registrovan");
    xsw.writeCharacters(Uzivatel.formatData.format(u.getRegistrovan()));
    xsw.writeEndElement();
    xsw.writeEndElement();
}

A máme hotovo. Hotový program je ako vždy k stiahnutiu pod článkom. Nabudúce budeme cez SAX XML čítať.


 

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é 604x (4.24 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Úvod do formátu XML súborov v Jave
Všetky články v sekcii
Práca so súbormi v Jave
Preskočiť článok
(neodporúčame)
Čítanie XML súborov Saxe v Jave
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
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