Programování

Mapování XML na Javu, část 1

XML je horké. Protože XML je forma dat s vlastním popisem, lze jej použít ke kódování modelů bohatých dat. Je snadné vidět nástroj XML jako médium pro výměnu dat mezi velmi odlišnými systémy. Data lze snadno odhalit nebo publikovat jako XML ze všech druhů systémů: starší programy COBOL, databáze, programy C ++ atd.

TEXTOVÉ POLE:

TEXTBOX_HEAD: Mapování XML na Javu: Přečtěte si celou sérii!

  • Část 1 - Zaměstnejte rozhraní SAX API pro mapování dokumentů XML na objekty Java
  • Část 2 - Vytvořte knihovnu tříd, která používá rozhraní SAX API k mapování dokumentů XML na objekty Java

: END_TEXTBOX

Používání XML k vytváření systémů však představuje dvě výzvy. Za prvé, zatímco generování XML je přímočará procedura, inverzní operace využívající data XML z programu není. Zadruhé lze snadno chybně použít současné technologie XML, což programátorovi ponechá pomalý systém náročné na paměť. Velké požadavky na paměť a nízké rychlosti se ve skutečnosti mohou ukázat jako problematické pro systémy, které používají XML jako primární formát pro výměnu dat.

Některé standardní nástroje, které jsou v současné době k dispozici pro práci s XML, jsou lepší než jiné. Zejména SAX API má některé důležité runtime funkce pro kód citlivý na výkon. V tomto článku budeme rozvíjet některé vzory pro použití SAX API. Budete moci vytvořit rychlý mapovací kód XML na Java s minimální stopou paměti, a to i pro poměrně složité struktury XML (s výjimkou rekurzivních struktur).

V části 2 této série se budeme zabývat aplikací SAX API na rekurzivní struktury XML, ve kterých některé prvky XML představují seznamy seznamů. Budeme také vyvíjet knihovnu tříd, která spravuje navigační aspekty rozhraní SAX API. Tato knihovna zjednodušuje psaní XML mapovacího kódu na základě SAX.

Mapovací kód je podobný kompilaci kódu

Psaní programů využívajících data XML je jako psaní kompilátoru. To znamená, že většina překladačů převádí zdrojový kód na spustitelný program ve třech krocích. Nejprve, a lexer modul seskupuje znaky do slov nebo tokenů, které kompilátor rozpozná - proces známý jako tokenizace. Druhý modul s názvem analyzátor, analyzuje skupiny tokenů s cílem rozpoznat právní jazykové konstrukce. Poslední, třetí modul, generátor kódů, bere sadu konstruktů právního jazyka a generuje spustitelný kód. Někdy je syntaktická analýza a generování kódu smíchané.

Chcete-li použít data XML v programu Java, musíme podstoupit podobný proces. Nejprve analyzujeme každý znak v textu XML, abychom rozpoznali legální tokeny XML, jako jsou počáteční značky, atributy, koncové značky a oddíly CDATA.

Za druhé ověříme, že tokeny tvoří legální konstrukce XML. Pokud dokument XML sestává výhradně z legálních konstruktů podle specifikace XML 1.0, je dobře tvarovaný. Na nejzákladnější úrovni se musíme ujistit, že například všechny značky mají shodné otevírací a zavírací značky a atributy jsou v úvodní značce správně strukturovány.

Pokud je k dispozici DTD, máme také možnost zajistit, aby konstrukty XML nalezené během analýzy byly legální, pokud jde o DTD, a aby byly dobře vytvořené XML.

Nakonec použijeme data obsažená v dokumentu XML k dosažení něčeho užitečného - říkám tomu mapování XML do Javy.

Analyzátory XML

Naštěstí existují běžné komponenty - analyzátory XML - které pro nás provádějí některé z těchto úkolů souvisejících s kompilátory. Analyzátory XML za nás zpracovávají všechny lexikální analýzy a úlohy analýzy. Mnoho aktuálně dostupných analyzátorů XML založených na prostředí Java podporuje dva populární standardy syntaktické analýzy: API SAX a DOM.

Dostupnost běžného analyzátoru XML může vypadat, že těžká část používání XML v Javě byla pro vás hotová. Ve skutečnosti je použití běžného analyzátoru XML zahrnutým úkolem.

SAX a DOM API

Rozhraní SAX API je založeno na událostech. Analyzátory XML, které implementují rozhraní SAX API, generují události, které odpovídají různým funkcím nalezeným v analyzovaném dokumentu XML. Reagováním na tento proud událostí SAX v kódu Java můžete psát programy řízené daty založenými na XML.

DOM API je API založené na objektovém modelu. Analyzátory XML, které implementují DOM, vytvářejí obecný objektový model v paměti, který představuje obsah dokumentu XML. Jakmile syntaktický analyzátor XML dokončí analýzu, obsahuje paměť strom objektů DOM, který nabízí informace o struktuře i obsahu dokumentu XML.

Koncept DOM vyrostl ze světa prohlížeče HTML, kde běžný objektový model dokumentu představuje dokument HTML načtený v prohlížeči. Tento HTML DOM je poté k dispozici pro skriptovací jazyky, jako je JavaScript. HTML DOM byl v této aplikaci velmi úspěšný.

Nebezpečí DOM

Na první pohled se DOM API zdá být bohatší na funkce, a proto lepší než API SAX. DOM má však vážné problémy s účinností, které mohou poškodit aplikace citlivé na výkon.

Aktuální skupina analyzátorů XML, které podporují DOM, implementuje objektový model v paměti vytvořením mnoha drobných objektů, které představují uzly DOM obsahující buď text, nebo jiné uzly DOM. Zní to dost přirozeně, ale má to negativní dopad na výkon. Jednou z nejdražších operací v Javě je Nový operátor. Odpovídajícím způsobem pro každého Nový operátor prováděný v Javě, musí sběrač odpadků JVM nakonec odebrat objekt z paměti, pokud na něj nezůstanou žádné odkazy. Rozhraní DOM API má tendenci skutečně mlátit paměťový systém JVM s mnoha malými objekty, které se obvykle brzy po analýze odhodí stranou.

Dalším problémem DOM je skutečnost, že načte celý dokument XML do paměti. U velkých dokumentů se z toho stává problém. Opět platí, že protože DOM je implementován jako mnoho drobných objektů, je paměťová stopa ještě větší než samotný dokument XML, protože JVM ukládá několik dalších bajtů informací týkajících se všech těchto objektů a také obsahu dokumentu XML.

Je také znepokojující, že mnoho programů Java ve skutečnosti nepoužívá obecnou strukturu objektů DOM. Místo toho, jakmile se struktura DOM načte do paměti, zkopírují data do objektového modelu specifického pro konkrétní problémovou doménu - jemný, ale nehospodárný proces.

Dalším jemným problémem pro rozhraní DOM API je, že pro něj napsaný kód musí dokument XML skenovat dvakrát. První průchod vytvoří strukturu DOM v paměti, druhý vyhledá všechna data XML, o která se program zajímá. Některé styly kódování mohou procházet strukturou DOM několikrát při hledání různých dat XML. Naproti tomu styl kódování SAX podporuje lokalizaci a sběr dat XML v jednom průchodu.

Některé z těchto problémů lze vyřešit lepším podkladovým designem datové struktury, který interně představuje objektový model DOM. V analyzátorech XML nelze řešit problémy, jako je podpora vícenásobného předávání zpracování a překlad mezi obecnými a konkrétními objektovými modely.

SAX pro přežití

Ve srovnání s DOM API je SAX API atraktivní přístup. SAX nemá obecný objektový model, takže nemá problémy s pamětí ani výkonem spojené se zneužíváním Nový operátor. A se SAX neexistuje žádný obecný objektový model, který byste ignorovali, pokud místo toho plánujete použít konkrétní objektový model problémové domény. Navíc, protože SAX zpracovává dokument XML v jednom průchodu, vyžaduje mnohem méně času na zpracování.

SAX má několik nevýhod, ale většinou souvisí s programátorem, nikoli s běhovým výkonem API. Podívejme se na pár.

První nevýhoda je koncepční. Programátoři jsou zvyklí navigovat za účelem získání dat; Chcete-li najít soubor na souborovém serveru, procházíte změnou adresářů. Podobně pro získání dat z databáze napíšete dotaz SQL pro data, která potřebujete. U SAX je tento model obrácen. To znamená, že nastavíte kód, který naslouchá seznamu všech dostupných dostupných dat XML. Tento kód se aktivuje, pouze když jsou uvedena zajímavá data XML. Zpočátku se SAX API zdá divné, ale po nějaké době se myšlení tímto obráceným způsobem stává druhou přirozeností.

Druhá nevýhoda je nebezpečnější. S kódem SAX se naivní přístup „pojďme to hacknout“ celkem rychle vypaří, protože analyzátor SAX vyčerpávajícím způsobem naviguje strukturu XML a současně dodává data uložená v dokumentu XML. Většina lidí se zaměřuje na aspekt mapování dat a navigační aspekt zanedbává. Pokud přímo neřešíte navigační aspekt syntaktické analýzy SAX, kód, který sleduje polohu ve struktuře XML během syntaktické analýzy SAX, se rozšíří a bude mít mnoho jemných interakcí. Tento problém je podobný problémům spojeným s nadměrnou závislostí na globálních proměnných. Pokud se ale naučíte správně strukturovat kód SAX, aby se nestal nepraktickým, je to přímočařejší než použití rozhraní DOM API.

Základní SAX

V současné době existují dvě publikované verze rozhraní SAX API. Pro naše příklady použijeme verzi 2 (viz Zdroje). Verze 2 používá jiné názvy tříd a metod než verze 1, ale struktura kódu je stejná.

SAX je API, nikoli analyzátor, takže tento kód je obecný napříč analyzátory XML. Chcete-li spustit příklady, budete muset přistupovat k analyzátoru XML, který podporuje SAX v2. Používám analyzátor Apache Xerces. (Viz Zdroje.) Podrobnější informace o vyvolání analyzátoru SAX najdete v úvodní příručce vašeho analyzátoru.

Specifikace API SAX je docela přímočará. In obsahuje mnoho podrobností, ale jeho primárním úkolem je vytvořit třídu, která implementuje ContentHandler interface, rozhraní zpětného volání používané analyzátory XML k informování vašeho programu o událostech SAX, které se nacházejí v dokumentu XML.

SAX API také pohodlně dodává a DefaultHandler implementační třída pro ContentHandler rozhraní.

Jakmile implementujete ContentHandler nebo prodloužil DefaultHandler, k analýze konkrétního dokumentu stačí nasměrovat analyzátor XML.

Náš první příklad rozšiřuje DefaultHandler vytisknout každou událost SAX do konzoly. Takto získáte představu o tom, jaké události SAX budou generovány a v jakém pořadí.

Chcete-li začít, zde je ukázkový dokument XML, který použijeme v našem prvním příkladu:

   Bob New York 

Dále vidíme zdrojový kód pro mapovací kód XML prvního příkladu:

import org.xml.sax. *; importovat org.xml.sax.helpers. *; importovat java.io. *; public class Example1 extends DefaultHandler {// Override methods of the DefaultHandler class // to obtain notification of SAX Events. // // Viz org.xml.sax.ContentHandler pro všechny dostupné události. // public void startDocument () vyvolá SAXException {System.out.println ("Událost SAX: START DOKUMENTU"); } public void endDocument () hodí SAXException {System.out.println ("Událost SAX: END DOCUMENT"); } public void startElement (String namespaceURI, String localName, String qName, Attributes attr) hodí SAXException {System.out.println ("Událost SAX: START ELEMENT [" + localName + "]"); // Také vytiskneme atributy, pokud // existují nějaké ... 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) vyvolá SAXException {System.out.print ("Událost SAX: CHARACTERS ["); try {OutputStreamWriter outw = new OutputStreamWriter (System.out); outw.write (ch, start, length); outw.flush (); } catch (Výjimka e) {e.printStackTrace (); } System.out.println ("]"); } public static void main (String [] argv) {System.out.println ("Příklad1 Události SAX:"); try {// Create SAX 2 parser ... XMLReader xr = XMLReaderFactory.createXMLReader (); // Nastavit ContentHandler ... xr.setContentHandler (nový Example1 ()); // Analyzovat soubor ... xr.parse (new InputSource (new FileReader ("Example1.xml")))); } catch (Výjimka e) {e.printStackTrace (); }}} 

Nakonec je zde výstup generovaný spuštěním prvního příkladu s naším ukázkovým dokumentem XML:

Příklad 1 Události SAX: Událost SAX: SPUŠTĚNÍ DOKUMENTU Událost SAX: SPUŠTĚNÍ PRVKU [jednoduchý] ATTRIBUTE: datum HODNOTA: 7. 7. 2000 Událost SAX: CHARACTERS [] Událost SAX: START ELEMENT [jméno] Událost SAX: CHARACTERS [Bob] Událost 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] Událost SAX: KONEC DOKUMENTU 

Jak vidíte, analyzátor SAX zavolá příslušné ContentHandler metoda pro každou událost SAX, kterou objeví v dokumentu XML.

Ahoj světe

Nyní, když rozumíme základnímu vzoru SAX, můžeme začít dělat něco trochu užitečného: extrahovat hodnoty z našeho jednoduchého dokumentu XML a demonstrovat klasický program hello world.

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