Java a XML Java i XML jsou přenositelné V javě existuje podpora pro práci s XML, nejčastější akce prováděné při zpracování XML: načítání XML elementů generování nových elementů nebo úprava starého zápis do XML dokumentu transformace XML do jiných formátů Parsování XML Java obsahuje množství knihoven pro práci s XML, provedou rozdělení XML do jednotlivých částí = parsování. Těmto nástrojům se říká parsery a bývají součástí každého moderního programovacího jazyka. Parser by měl umět: číst XML dokument a kontrolovat jeho strukturu, validovat podle DTD nebo XSD během čtení extrahovat názvy a hodnoty elementů a atributů nabízí abstraktní model XML dokumentu = infoset Parsery se dělí podle zvoleného způsobu zpracování, každý způsob je popsán pomocí svého API = programátorské rozhraní. Základní dělení: proudové čtení stromová reprezentace dokumentu Proudové čtení Typickým představitelem SAX = Simple API for XML. Pro každou ucelenou část vyvolává událost, naším úkolem je napsat obsluhy těchto událostí (viz. návrhový vzor vydavatelodběratel). Výhody: velká rychlost malá paměťová náročnost podporované API, je součástí Java Core API od JDK 1.4 Nevýhody: dokument se zpracovává sekvenčně, při čtení se nelze vracet načtené zpracovává nebo někam ukládá Stromová prezentace dokumentu Celý dokument se načte naráz do stromové struktury v paměti. Typickým představitelem je DOM = Document Object Model. Výhody: celý infoset je najednou dostupný v paměti načtený dokumet se může měnit stejně jako SAX je DOM podporované od JDK 1.4 výhodou dobrá spolupráce s jazykem XPath = XML Path Language Nevýhody: malá rychlost načítání velká paměťová náročnost 10/26/09 1/7 Java a XML
Příklad - Proudové čtení import javax.xml.parsers.*; public class ParsovaniXML { private static final String SOUBOR = "vyukovyprogram/texty/uvod.xml"; public static void main(string[] args) { try { /* vytvoření universálního parseru */ SAXParserFactory unipar = SAXParserFactory.newInstance(); /* validace podle souboru DTD nebo XSD unipar.setvalidating(false); */ /* vytvoření objektu parseru starší verze SAX1 (použit implicitní parser Xerces */ SAXParser parsersax1 = unipar.newsaxparser(); /* vytvoření objektu parseru vyšší verze SAX2 */ XMLReader parser = parsersax1.getxmlreader(); /* nastavení reakce na chyby souboru XML */ parser.seterrorhandler(new ChybyZjisteneParserem()); /* nastavení obsluh pro čtení XML dat pomocí prázdného adaptéru - ten nic nedělá: parser.setcontenthandler(new DefaultHandler()); nebo pomocí mého adaptéru, který dědí od DefaultHandler */ MujHandler handler = new MujHandler(); parser.setcontenthandler(handler); /* parserování určitého souboru */ parser.parse(soubor); handler.text(); System.out.println(SOUBOR + "přečten bez chyb"); catch(exception e) { e.printstacktrace(); Proudové čtení používáme metody: public void startdocument() public void startelement(string uri, String localname, String qname, Attributes attrs) public void characters(char[] ch, int start, int delka) public void endelement(string uri, String localname, String qname) public void enddocument() kde uri... URI jménného prostoru, není-li použit, je prázdný localname... jméno lementu v souvislosti se jmenným prostorem, když není použit, je prázdné!!! 10/26/09 2/7 Java a XML
qname... úplné jméno elementu atts... seznam atributů ch... pole znaků, ve kterých je uložena hodnota elementu, pro krátké xml je to celý textový soubor start... index počátečního znaku aktuální hodnoty length... počet znaků 1. Hodnota elementu může přijít po částech - v několika voláních metody chatacter(), proto je zapotřebí je ukládat postupně do StringBufferu a spojovat. 2. ch obsahuje i znaky mezi elementy (např. odřádkování), je zapotřebí kontrolovat, jestli jsme uvnitř konkrétního elementu package XML; public class ChybyZjisteneParserem implements ErrorHandler { /* vytvoření textu hlášení */ private String texthlaseni(saxparseexception e) { return e.getsystemid() + "\n" + "radka: " + e.getlinenumber() + " sloupec: " + e.getcolumnnumber() + "\n" + e.getmessage(); /* obsluha varovných hlášení */ public void warning(saxparseexception e) { System.out.println("Varování: " + texthlaseni(e)); /* obsluha chyb */ public void error(saxparseexception e) throws SAXException { throw new SAXException("Chyba: " + texthlaseni(e)); /* obsluha fatálních chyb */ public void fatalerror(saxparseexception e) throws SAXException { throw new SAXException("Kritická chyba: " + texthlaseni(e)); //import javax.xml.parsers.*; public class MujHandler extends DefaultHandler { private static final int VELIKOST_BUFFERU = 10000; private StringBuffer hodnota = new StringBuffer(VELIKOST_BUFFERU); public void text() { System.out.println(hodnota); public void startdocument() { hodnota.setlength(0); 10/26/09 3/7 Java a XML
public void startelement(string uri, String localname, String qname, Attributes attrs) { if(qname.equals("podnadpis")) hodnota.append("\n"); hodnota.append("\n* " + qname + "\n\t"); public void characters(char[] ch, int start, int delka) { hodnota.append(ch, start, delka); public void endelement(string uri, String localname, String qname) { hodnota.append("\n* /" + qname); jidlo.xml <?xml version="1.0" encoding="utf-8"?> <jidlo> <ovoce cislo="1"> <nazev jednotkovacena="10">jablka</nazev> <vaha>2.5</vaha> <ovoce cislo="2"> <nazev jednotkovacena="25">banány</nazev> <vaha>2</vaha> <ovoce cislo="3"> <nazev jednotkovacena="19">grapefruidy</nazev> <vaha>0.75</vaha> <ovoce cislo="4"> <nazev jednotkovacena="32">švestky sušené</nazev> <vaha>1.8</vaha> </jidlo> Převod infosetu na seznam objektů Napíšeme si odpovídající třídu: public class Ovoce { int cislo; String nazev; int jednotkovacena; double vaha; public Ovoce(int cislo, String nazev, int jednotkovacena, double vaha) { this.cislo = cislo; this.nazev = nazev; this.jednotkovacena = jednotkovacena; this.vaha = vaha; public String tostring() { return "" + cislo + ". " + nazev + " - " + vaha + " [kg] po " + jednotkovacena + " [Kc] = " + vaha*jednotkovacena + " [Kc]"; V paměti budou vzniklé objekty třídy Ovoce uloženy v seznamu typu ArrayList<Ovoce>, ze kteréhoje možné kdykoliv získat potřebné informace. 10/26/09 4/7 Java a XML
Mohu zjistit například celkovou váhu a celkovou cenu ovoce: /* získání obsahu testu ze souboru xml */ VseVPametiSAX pars = new VseVPametiSAX(cestaTest + soubor); ArrayList<Otazka> ot = new ArrayList<Otazka>(); ot = pars.getseznam(); import javax.xml.parsers.*; import java.util.*; public class VseVPametiSAX { private String soubor; private static ArrayList<Otazka> ot = new ArrayList<Otazka>(); public ArrayList<Otazka> getseznam() { return ot; public VseVPametiSAX(String soubor) { this.soubor=soubor; try { /* vytvoření universálního parseru */ SAXParserFactory unipar = SAXParserFactory.newInstance(); /* validace podle souboru DTD nebo XSD unipar.setvalidating(false); */ /* vytvoření objektu parseru starší verze SAX1 (použit implicitní parser Xerces */ SAXParser parsersax1 = unipar.newsaxparser(); /* vytvoření objektu parseru vyšší verze SAX2 */ XMLReader parser = parsersax1.getxmlreader(); /* nastavení reakce na chyby souboru XML */ parser.seterrorhandler(new ChybyZjisteneParserem()); /* nastavení obsluh pro čtení XML dat pomocí prázdného adaptéru - ten nic nedělá: parser.setcontenthandler(new DefaultHandler()); nebo pomocí mého adaptéru, který dědí od DefaultHandler */ VseVPametiHandler handler = new VseVPametiHandler(); parser.setcontenthandler(handler); /* parserování určitého souboru */ parser.parse(soubor); ot = handler.getseznam(); catch(exception e) { e.printstacktrace(); import java.util.*; 10/26/09 5/7 Java a XML
public class VseVPametiHandler extends DefaultHandler { private static ArrayList<Otazka> ot = new ArrayList<Otazka>(); private static final int VELIKOST_BUFFERU = 1000; private StringBuffer hodnota = new StringBuffer(VELIKOST_BUFFERU); private boolean uvnitrzneni = false; private boolean uvnitra = false; private boolean uvnitrb = false; private boolean uvnitrc = false; private boolean uvnitrd = false; private boolean uvnitrspravne = false; String zneni; String a; String b; String c; String d; char spravne; public ArrayList<Otazka> getseznam() { return ot; public void startdocument() { ot.clear(); public void startelement(string uri, String localname, String qname, Attributes attrs) { hodnota.setlength(0); if (qname.equals("zneni") == true) uvnitrzneni = true; else if (qname.equals("a") == true) uvnitra = true; else if (qname.equals("b") == true) uvnitrb = true; else if (qname.equals("c") == true) uvnitrc = true; else if (qname.equals("d") == true) uvnitrd = true; else if (qname.equals("spravne") == true) uvnitrspravne = true; public void characters(char[] ch, int start, int delka) { if (uvnitrzneni == true uvnitra == true uvnitrb == true uvnitrc == true uvnitrd == true uvnitrspravne == true) hodnota.append(ch, start, delka); public void endelement(string uri, String localname, String qname) { if (uvnitrzneni == true) { zneni = hodnota.tostring(); uvnitrzneni = false; else if (uvnitra == true) { a = hodnota.tostring(); uvnitra = false; else if (uvnitrb == true) { b = hodnota.tostring(); uvnitrb = false; else if (uvnitrc == true) { c = hodnota.tostring(); uvnitrc = false; else if (uvnitrd == true) { 10/26/09 6/7 Java a XML
d = hodnota.tostring(); uvnitrd = false; else if (uvnitrspravne == true) { spravne = hodnota.tostring().charat(0); uvnitrspravne = false; else if (qname.equals("otazka") == true) { ot.add(new Otazka(zneni, a, b, c, d, spravne)); /* public void enddocument() { System.out.println("pocet prvku v kolekci: " + ot.size()); */ SAX... http://www.kiv.zcu.cz/~herout/java/ujj4/index.html vytvořím objekt parseru (implicitním parserem je Xerces) vytvořím obálku pro univerzální parser nastavení konfigurace pro budoucí parser vytvoří nový parser nastavenení reakcí na chyby zpracování parsovaného XML dokumentu převod infosetu na seznam objektů //pridat novy objekt 10/26/09 7/7 Java a XML