Programovanie

Mapovanie XML na Javu, časť 1

XML je populárne. Pretože XML je forma údajov s vlastným popisom, dá sa použiť na kódovanie bohatých dátových modelov. Je ľahké vidieť nástroj XML ako médium na výmenu údajov medzi veľmi odlišnými systémami. Dáta môžu byť ľahko odkryté alebo publikované ako XML zo všetkých druhov systémov: zo starších programov COBOL, databáz, programov C ++ atď.

TEXTOVÉ POLE:

TEXTBOX_HEAD: Mapovanie XML na Javu: Prečítajte si celú sériu!

  • 1. časť - Využite rozhranie SAX API na mapovanie dokumentov XML na objekty Java
  • 2. časť - Vytvorte knižnicu tried, ktorá používa rozhranie SAX API na mapovanie dokumentov XML na objekty Java

: END_TEXTBOX

Používanie XML na vytváranie systémov však predstavuje dve výzvy. Po prvé, zatiaľ čo generovanie XML je jednoduchý postup, inverzná operácia pomocou údajov XML z programu nie je. Po druhé, súčasné technológie XML sa dajú ľahko nesprávne uplatniť, čo môže ponechať programátorovi pomalý systém náročný na pamäť. Vysoké požiadavky na pamäť a pomalé rýchlosti sa v skutočnosti môžu ukázať ako problematické pre systémy, ktoré používajú XML ako svoj primárny formát výmeny údajov.

Niektoré štandardné nástroje, ktoré sú v súčasnosti k dispozícii na prácu s XML, sú lepšie ako iné. Najmä SAX API má niektoré dôležité runtime funkcie pre kód citlivý na výkon. V tomto článku vypracujeme niekoľko vzorov pre aplikáciu SAX API. Budete schopní vytvárať rýchly mapovací kód XML na Java s minimálnou stopou pamäte, a to aj pre pomerne zložité štruktúry XML (s výnimkou rekurzívnych štruktúr).

V časti 2 tejto série sa budeme venovať aplikácii SAX API na rekurzívne štruktúry XML, v ktorých niektoré prvky XML predstavujú zoznamy zoznamov. Vyvinieme tiež knižnicu tried, ktorá bude riadiť navigačné aspekty SAX API. Táto knižnica zjednodušuje písanie mapovacieho kódu XML na základe SAX.

Mapovací kód je podobný kompilácii kódu

Písanie programov, ktoré využívajú údaje XML, je ako písanie kompilátora. To znamená, že väčšina kompilátorov prevádza zdrojový kód na spustiteľný program v troch krokoch. Najskôr a lexer modul zoskupuje znaky do slov alebo tokenov, ktoré kompilátor rozpozná - proces známy ako tokenizácia. Druhý modul sa volá analyzátor, analyzuje skupiny tokenov s cieľom rozpoznať právne jazykové konštrukcie. Posledný, tretí modul, generátor kódu, berie sadu konštruktov právneho jazyka a generuje spustiteľný kód. Niekedy je syntaktická analýza a generovanie kódu zmiešané.

Aby sme mohli použiť údaje XML v programe Java, musíme podstúpiť podobný proces. Najskôr analyzujeme každý znak v texte XML, aby sme rozpoznali legálne tokeny XML, ako sú počiatočné značky, atribúty, koncové značky a oddiely CDATA.

Po druhé overíme, či tokeny tvoria legálne konštrukcie XML. Ak dokument XML pozostáva výlučne z právnych konštruktov podľa špecifikácie XML 1.0, je to tak dobre formovaný. Na najzákladnejšej úrovni sa musíme ubezpečiť, že napríklad všetky značky majú zodpovedajúce úvodné a záverečné značky a atribúty sú v úvodnej značke správne štruktúrované.

Ak je k dispozícii aj DTD, máme možnosť zaistiť, aby boli konštrukty XML nájdené počas syntaktickej analýzy legálne z hľadiska DTD, ako aj aby boli dobre tvarované XML.

Nakoniec použijeme údaje obsiahnuté v dokumente XML, aby sme dosiahli niečo užitočné - toto mapovanie XML nazývam Java.

Analyzátory XML

Našťastie existujú hotové komponenty - analyzátory XML -, ktoré za nás vykonávajú niektoré z týchto úloh súvisiacich s kompilátormi. Analyzátory XML za nás vybavujú všetky úlohy spojené s lexikálnou analýzou a analýzou. Mnoho v súčasnosti dostupných syntaktických analyzátorov XML založených na prostredí Java podporuje dva populárne štandardy syntaktickej analýzy: API SAX a DOM.

Dostupnosť dostupného syntaktického analyzátora XML môže spôsobiť, že sa zdá, že náročná časť používania XML v jazyku Java bola urobená za vás. V skutočnosti je použitie hotového analyzátora XML dôležitou úlohou.

SAX a DOM API

Rozhranie SAX API je založené na udalostiach. Analyzátory XML, ktoré implementujú SAX API, generujú udalosti, ktoré zodpovedajú rôznym funkciám nájdeným v analyzovanom dokumente XML. Reagovaním na tento prúd udalostí SAX v kóde Java môžete písať programy riadené údajmi založenými na XML.

DOM API je API založené na objektovom modeli. Analyzátory XML, ktoré implementujú DOM, vytvárajú v pamäti generický objektový model, ktorý predstavuje obsah dokumentu XML. Keď syntaktický analyzátor XML dokončí syntaktickú analýzu, pamäť obsahuje strom objektov DOM, ktorý ponúka informácie o štruktúre aj obsahu dokumentu XML.

Koncept DOM vyrástol zo sveta prehliadača HTML, kde bežný objektový model dokumentu predstavuje dokument HTML načítaný v prehliadači. Tento HTML DOM je potom k dispozícii pre skriptovacie jazyky, ako je JavaScript. HTML DOM bol v tejto aplikácii veľmi úspešný.

Nebezpečenstvo DOM

Na prvý pohľad sa zdá, že DOM API je bohatšie na funkcie, a teda lepšie ako API SAX. DOM má však vážne problémy s efektívnosťou, ktoré môžu poškodiť aplikácie citlivé na výkon.

Aktuálna skupina analyzátorov XML, ktoré podporujú DOM, implementuje objektový model v pamäti vytvorením mnohých drobných objektov, ktoré predstavujú uzly DOM obsahujúce buď text, alebo iné uzly DOM. Znie to dosť prirodzene, ale má to negatívny dopad na výkon. Jednou z najdrahších operácií v Jave je Nový operátor. Zodpovedajúcim spôsobom pre každého Nový operátor vykonaný v Jave, zberač odpadu JVM musí nakoniec odstrániť objekt z pamäte, keď na objekt nezostanú žiadne odkazy. Rozhranie DOM API má tendenciu skutočne mlátiť pamäťový systém JVM s mnohými malými objektmi, ktoré sa zvyčajne čoskoro po analýze odhodia nabok.

Ďalším problémom DOM je skutočnosť, že načíta celý dokument XML do pamäte. Pri veľkých dokumentoch to predstavuje problém. Pretože DOM je implementovaný ako veľa drobných objektov, pamäťová stopa je ešte väčšia ako samotný dokument XML, pretože JVM ukladá niekoľko ďalších bajtov informácií týkajúcich sa všetkých týchto objektov, ako aj obsahu dokumentu XML.

Je tiež znepokojujúce, že veľa programov Java v skutočnosti nepoužíva generickú objektovú štruktúru DOM. Namiesto toho, akonáhle sa štruktúra DOM načíta do pamäte, skopírujú údaje do objektového modelu špecifického pre konkrétnu problémovú doménu - jemný, ale zbytočný proces.

Ďalším jemným problémom rozhrania DOM API je, že kód, ktorý je preň napísaný, musí dokument XML skenovať dvakrát. Prvý prechod vytvorí štruktúru DOM v pamäti, druhý vyhľadá všetky údaje XML, o ktoré sa program zaujíma. Niektoré štýly kódovania môžu pri vyhľadávaní rôznych častí údajov XML prechádzať štruktúrou DOM ešte niekoľkokrát. Štýl kódovania SAX naopak podporuje lokalizáciu a zhromažďovanie údajov XML v jednom priechode.

Niektoré z týchto problémov je možné vyriešiť lepším podkladovým dizajnom dátovej štruktúry, ktorý interne predstavuje objektový model DOM. V analyzátoroch XML nie je možné vyriešiť problémy, ako napríklad podpora viacerých spracovaní a preklad medzi generickými a konkrétnymi objektovými modelmi.

SAX pre prežitie

V porovnaní s DOM API je SAX API atraktívnym prístupom. SAX nemá generický objektový model, takže nemá problémy s pamäťou alebo výkonom spojené so zneužívaním Nový operátor. A v prípade SAX neexistuje generický objektový model, ktorý by ste ignorovali, ak plánujete namiesto toho použiť konkrétny objektový model problémovej domény. Pretože SAX spracováva dokument XML v jednom prechode, vyžaduje si to oveľa menej času na spracovanie.

SAX má niekoľko nevýhod, ale väčšinou súvisia s programátorom, nie s runtime výkonom API. Pozrime sa na niekoľko.

Prvý nedostatok je koncepčný. Programátori sú zvyknutí navigovať za účelom získania údajov; ak chcete nájsť súbor na súborovom serveri, prechádzate zmenou adresárov. Podobne, aby ste získali údaje z databázy, napíšete dotaz SQL pre údaje, ktoré potrebujete. So systémom SAX je tento model obrátený. To znamená, že nastavíte kód, ktorý počúva zoznam všetkých dostupných dostupných údajov XML. Tento kód sa aktivuje, iba keď sú uvedené zaujímavé údaje XML. Spočiatku sa SAX API javí ako čudné, ale po chvíli sa uvažovanie týmto obráteným spôsobom stáva druhou prirodzenosťou.

Druhá nevýhoda je nebezpečnejšia. Pri kóde SAX sa naivný prístup „poďme na to hacknúť“ pomerne rýchlo vypaľuje, pretože syntaktický analyzátor SAX vyčerpávajúco naviguje v štruktúre XML a súčasne dodáva dáta uložené v dokumente XML. Väčšina ľudí sa zameriava na aspekt mapovania údajov a zanedbáva navigačný aspekt. Ak priamo neriešite navigačný aspekt syntaktickej analýzy SAX, kód, ktorý počas syntaktickej analýzy SAX sleduje polohu v rámci štruktúry XML, sa rozšíri a bude mať veľa jemných interakcií. Tento problém je podobný problémom spojeným s nadmernou závislosťou od globálnych premenných. Ak sa ale naučíte správne štruktúrovať kód SAX, aby sa nestal nepraktickým, je to priamočiarejšie ako použitie rozhrania DOM API.

Základný SAX

V súčasnosti existujú dve zverejnené verzie rozhrania SAX API. Pre naše príklady použijeme verziu 2 (pozri Zdroje). Verzia 2 používa iné názvy tried a metód ako verzia 1, ale štruktúra kódu je rovnaká.

SAX je API, nie analyzátor, takže tento kód je všeobecný pre všetky analyzátory XML. Aby ste mohli spustiť príklady, budete musieť získať prístup k analyzátoru XML, ktorý podporuje SAX v2. Používam analyzátor Apache Xerces. (Pozri Zdroje.) Podrobnosti o vyvolaní syntaktického analyzátora SAX nájdete v príručke pre začínajúcich syntaktických analyzátorov.

Špecifikácia API SAX je dosť jasná. In obsahuje veľa detailov, ale jeho primárnou úlohou je vytvoriť triedu, ktorá implementuje ContentHandler interface, rozhranie spätného volania používané analyzátormi XML na informovanie vášho programu o udalostiach SAX, ktoré sa nachádzajú v dokumente XML.

SAX API tiež pohodlne dodáva a DefaultHandler implementačná trieda pre ContentHandler rozhranie.

Po implementácii ContentHandler alebo predĺžil DefaultHandler, na analýzu konkrétneho dokumentu stačí nasmerovať syntaktický analyzátor XML.

Náš prvý príklad rozširuje DefaultHandler vytlačiť každú udalosť SAX na konzolu. Takto získate prehľad o tom, aké udalosti SAX sa budú generovať a v akom poradí.

Na začiatok uvádzame ukážkový dokument XML, ktorý použijeme v prvom príklade:

   Bob New York 

Ďalej vidíme zdrojový kód pre mapovací kód XML z prvého príkladu:

import org.xml.sax. *; importovať org.xml.sax.helpers. *; import java.io. *; verejná trieda Example1 rozširuje DefaultHandler {// Prepíše metódy triedy DefaultHandler //, aby získala upozornenie na udalosti SAX. // // Všetky dostupné udalosti nájdete na org.xml.sax.ContentHandler. // public void startDocument () hodí SAXException {System.out.println ("SAX Event: START DOCUMENT"); } public void endDocument () hodí SAXException {System.out.println ("Udalosť SAX: END DOCUMENT"); } public void startElement (Reťazec namespaceURI, Reťazec localName, Reťazec qName, Atribúty attr) vyvolá SAXException {System.out.println ("Udalosť SAX: START ELEMENT [" + localName + "]"); // Vytlačme tiež atribúty, ak // existujú nejaké ... for (int i = 0; i <attr.getLength (); i ++) {System.out.println ("ATTRIBUTE:" + attr.getLocalName ( i) + "HODNOTA:" + attr.getValue (i)); }} public void endElement (String namespaceURI, String localName, String qName) throws SAXException {System.out.println ("SAX Event: END ELEMENT [" + localName + "]")); } znaky public void (char [] ch, int start, int length) hodí SAXException {System.out.print ("SAX Event: CHARACTERS ["); skúsiť {OutputStreamWriter outw = nový OutputStreamWriter (System.out); outw.write (ch, start, length); outw.flush (); } catch (Výnimka e) {e.printStackTrace (); } System.out.println ("]"); } public static void main (String [] argv) {System.out.println ("Example1 SAX Events:"); try {// Create SAX 2 parser ... XMLReader xr = XMLReaderFactory.createXMLReader (); // Nastaviť ContentHandler ... xr.setContentHandler (nový Example1 ()); // Analyzovať súbor ... xr.parse (nový InputSource (nový FileReader ("Example1.xml"))); } catch (Výnimka e) {e.printStackTrace (); }}} 

Nakoniec je tu výstup generovaný spustením prvého príkladu s našim vzorovým dokumentom XML:

Príklad1 Udalosti SAX: Udalosť SAX: ZAČIATOK DOKUMENTU Udalosť SAX: ZAČAŤ ELEMENT [jednoduchý] ATRIBÚT: dátum HODNOTA: 7. 7. 2000 Udalosť SAX: CHARACTERS [] Udalosť SAX: ZAČIATOK PRVKU [meno] Udalosť SAX: POSTAVY [Bob] Udalosť SAX : END ELEMENT [name] SAX Event: CHARACTERS [] SAX Event: START ELEMENT [location] SAX Event: CHARACTERS [New York] SAX Event: END ELEMENT [location] SAX Event: CHARACTERS [] SAX Event: END ELEMENT [simple] Udalosť SAX: KONIEC DOKUMENTU 

Ako vidíte, syntaktický analyzátor SAX zavolá príslušné ContentHandler metóda pre každú udalosť SAX, ktorú objaví v dokumente XML.

Ahoj svet

Teraz, keď rozumieme základnému vzoru SAX, môžeme začať robiť niečo mierne užitočné: extrahovať hodnoty z nášho jednoduchého dokumentu XML a predviesť klasický program ahoj svet.

$config[zx-auto] not found$config[zx-overlay] not found