Programování

Programování XML v Javě, část 1

Takže rozumíte (víceméně) tomu, jak byste reprezentovali svá data v XML, a máte zájem o použití XML k vyřešení mnoha vašich problémů se správou dat. Přesto si nejste jisti, jak používat XML s vašimi programy Java.

TEXTBOX: TEXTBOX_HEAD: Programování XML v Javě: Přečtěte si celou sérii!

  • Část 1. Použijte Simple API for XML (SAX) ke snadnému zpracování XML v Javě
  • Část 2. Zjistěte více o ověření SAX a XML na názorných příkladech
  • Část 3. DOMINACE: Převezměte kontrolu nad strukturovanými dokumenty pomocí Objektového modelu dokumentu

: END_TEXTBOX

Tento článek navazuje na můj úvodní článek „XML pro absolutní začátečníky“, který vyšel v dubnu 1999 JavaWorld (viz URL níže v části Zdroje). Tento článek popisoval XML; Nyní budu stavět na tomto popisu a podrobně ukážu, jak vytvořit aplikaci, která používá Simple API for Java (SAX), lehký a výkonný standardní Java API pro zpracování XML.

Ukázkový kód použitý zde používá rozhraní SAX API ke čtení souboru XML a vytvoření užitečné struktury objektů. Než dokončíte tento článek, budete připraveni vytvářet vlastní aplikace založené na XML.

Cnost lenivosti

Larry Wall, šílený geniální tvůrce Perlu (druhého největšího programovacího jazyka v existenci), uvedl, že lenost je jednou ze „tří velkých ctností“ programátora (další dvě jsou netrpělivost a arogance). Lenost je ctnost, protože líný programátor půjde téměř na jakoukoli délku, aby se vyhnul práci, a to i při vytváření obecných, opakovaně použitelných programovacích rámců, které lze opakovaně použít. Vytvoření takových rámců vyžaduje spoustu práce, ale čas ušetřený na budoucích úkolech více než vynahradí počáteční investované úsilí. Nejlepší rámce umožňují programátorům dělat úžasné věci s malou nebo žádnou prací - a proto je lenost ctnostná.

XML je umožňující technologie pro ctnostného (líného) programátora. Základní analyzátor XML dělá pro programátora hodně práce, rozpoznává tokeny, překládá kódované znaky, vynucuje pravidla pro strukturu souborů XML, kontroluje platnost některých datových hodnot a případně volá na kód pro konkrétní aplikaci. Ve skutečnosti včasná standardizace v kombinaci s tvrdě konkurenčním trhem přinesla desítky svobodně dostupné implementace standardních analyzátorů XML v mnoha jazycích, včetně C, C ++, Tcl, Perl, Python a samozřejmě Java.

SAX API je jedno z nejjednodušších a nejlehčích rozhraní pro zpracování XML. V tomto článku použiji implementaci SAX XML4J od IBM, ale protože je API standardizované, může vaše aplikace nahradit jakýkoli balíček, který implementuje SAX.

SAX je API založené na událostech, fungující na principu zpětného volání. Aplikační programátor obvykle vytvoří SAX Analyzátor objekt a předejte jej jak vstupní XML, tak i a obsluha dokumentů, který přijímá zpětná volání pro události SAX. SAX Analyzátor převede svůj vstup na proud Události odpovídající strukturálním vlastnostem vstupu, jako jsou tagy XML nebo bloky textu. Při každé události se předá příslušné metodě obslužné rutiny dokumentu definované programátorem, která implementuje rozhraní zpětného volání org.xml.sax.DocumentHandler. Metody v této třídě obslužné rutiny provádějí během analýzy funkce specifické pro aplikaci.

Představte si například, že analyzátor SAX obdrží dokument obsahující malý dokument XML zobrazený v seznamu 1 níže. (Viz Zdroje pro soubor XML.)

 Blechy Ogden Nash, které Adam měl. 

Výpis 1. XML představující krátkou báseň

Když analyzátor SAX narazí na tag, volá uživatelem definované DocumentHandler.startElement () s řetězcem BÁSEŇ jako argument. Implementujete startElement () metoda dělat cokoli, co má aplikace dělat, když a BÁSEŇ začíná. Tok událostí a výsledná volání pro část XML výše se zobrazuje v tabulce 1 níže.

Tabulka 1. Sekvence zpětných volání, které SAX vytváří při analýze výpisu 1
Položka narazilaZpětné volání analyzátoru
{Začátek dokumentu}startDocument ()
startElement ("POEM", {AttributeList})
„\ n“znaků ("\ n ...", 6, 1)
startElement ("AUTHOR", {AttributeList})
„Ogden Nash“znaků ("\ n ...", 15, 10)
endElement („AUTHOR“)
„\ n“znaků ("\ n ...", 34, 1)
startElement ("TITLE", {AttributeList})
"Blechy"znaků ("\ n ...", 42, 5)
endElement („TITLE“)
„\ n“znaků ("\ n ...", 55, 1)
startElement ("LINE", {AttributeList})
"Adam"znaků ("\ n ...", 62, 4)
endElement ("LINE")
startElement ("LINE", {AttributeList})
„Měl jsem je.“znaků ("\ n ...", 67, 8)
endElement ("LINE")
„\ n“znaků ("\ n ...", 82, 1)
endElement ("POEM")
{Konec dokumentu}endDocument ()

Vytvoříte třídu, která se implementuje DocumentHandler reagovat na události, ke kterým dojde v analyzátoru SAX. Tyto Události nejsou události Java, jak je znáte z Abstract Windowing Toolkit (AWT). Jsou to podmínky, které analyzátor SAX detekuje při analýze, například začátek dokumentu nebo výskyt uzavírací značky ve vstupním proudu. Jakmile nastane každá z těchto podmínek (nebo událostí), volá SAX metodu odpovídající její podmínce DocumentHandler.

Klíčem k psaní programů, které zpracovávají XML pomocí SAX, je tedy zjistit, co DocumentHandler by měl dělat v reakci na proud zpětných volání metod ze SAX. Analyzátor SAX se stará o veškerou mechaniku identifikace značek, nahrazování hodnot entit atd., Takže se můžete soustředit na funkce specifické pro aplikaci, které používají data zakódovaná v XML.

Tabulka 1 zobrazuje pouze události spojené s prvky a znaky. SAX také zahrnuje zařízení pro zpracování dalších strukturálních funkcí souborů XML, jako jsou entity a pokyny ke zpracování, ale ty jsou nad rámec tohoto článku.

Vychytralý čtenář si všimne, že dokument XML lze reprezentovat jako strom typovaných objektů a že pořadí proudu událostí prezentovaného DocumentHandler odpovídá in-order traverálu stromu dokumentů v pořadí. (Není nutné tento bod chápat, ale koncept XML dokumentu jako stromové datové struktury je užitečný ve složitějších typech zpracování dokumentů, kterým se budeme věnovat v dalších článcích této série.)

Klíčem k pochopení toho, jak používat SAX, je porozumění DocumentHandler rozhraní, kterému se budu věnovat dále.

Přizpůsobte analyzátor pomocí org.xml.sax.DocumentHandler

Protože DocumentHandler rozhraní je tak zásadní pro zpracování XML pomocí SAX, stojí za to pochopit, co metody v rozhraní dělají. V této části se budu věnovat základním metodám a přeskočím ty, které se zabývají pokročilejšími tématy. Pamatovat si, DocumentHandler je rozhraní, takže metody, které popisuji, jsou metody, které implementujete pro zpracování funkcí specifických pro aplikaci, kdykoli dojde k odpovídající události.

Inicializace a vyčištění dokumentu

Analyzátor SAX XML pro každý analyzovaný dokument volá DocumentHandler metody rozhraní startDocument () (voláno před zahájením zpracování) a endDocument () (zavolá se po dokončení zpracování). Tyto metody můžete použít k inicializaci DocumentHandler připravit jej na příjem událostí a vyčistit nebo vyrobit výstup po dokončení analýzy. endDocument () je obzvláště zajímavý, protože se volá pouze v případě, že byl vstupní dokument úspěšně analyzován. Pokud Analyzátor generuje závažnou chybu, jednoduše přeruší stream událostí a přestane analyzovat, a endDocument () se nikdy nevolá.

Zpracování značek

Analyzátor SAX volá startElement () kdykoli narazí na otevřenou značku a endElement () kdykoli narazí na blízkou značku. Tyto metody často obsahují kód, který dělá většinu práce při analýze souboru XML. startElement ()Prvním argumentem je řetězec, což je název značky nalezeného prvku. Druhý argument je objekt typu AttributeList, rozhraní definované v balíčku org.xml.sax který poskytuje sekvenční nebo náhodný přístup k atributům prvků podle názvu. (Atributy jste již nepochybně viděli dříve v HTML; v řádku

, OKRAJ je atribut, jehož hodnota je "1"). Protože výpis 1 neobsahuje žádné atributy, nezobrazí se v tabulce 1. Příklady atributů v ukázkové aplikaci uvidíte dále v tomto článku.

Protože SAX neposkytuje žádné informace o kontextu prvků, se kterými se setkává (to objeví se uvnitř například v seznamu 1 výše), je na vás, abyste tyto informace poskytli. Programátoři aplikací často používají komíny startElement () a endElement (), tlačit objekty na hromádku, když prvek začíná, a vyskočit je ze zásobníku, když prvek končí.

Zpracovat bloky textu

The postavy() metoda označuje obsah znaků v dokumentu XML - jinými slovy znaky, které se neobjevují uvnitř značky XML. Podpis této metody je trochu zvláštní. První argument je pole bajtů, druhý je index do tohoto pole označující první znak rozsahu, který má být zpracován, a třetí argument je délka rozsahu znaků.

Mohlo by se zdát, že jednodušší API by jednoduše prošlo a Tětiva objekt obsahující data, ale postavy() byl definován tímto způsobem z důvodů efektivity. Analyzátor nemá žádný způsob, jak zjistit, zda použijete znaky, takže analyzátor analyzuje vstupní vyrovnávací paměť, předá odkaz na vyrovnávací paměť a indexy řetězce, který si prohlíží, a věří, že vytvoříte tvůj vlastní Tětiva pokud chcete. Je to trochu víc práce, ale umožňuje vám to rozhodnout se, zda za to zaplatíte nebo ne Tětiva konstrukce pro části obsahu v souboru XML.

The postavy() metoda zpracovává jak běžný textový obsah, tak obsah uvnitř sekcí CDATA, které se používají k zabránění parsování bloků doslovného textu analyzátorem XML.

Jiné metody

V souboru jsou tři další metody DocumentHandler rozhraní: ignorableWhitespace (), instrukce pro zpracování (), a setDocumentLocator (). ignorableWhitespace () hlásí výskyty prázdného prostoru a obvykle se nepoužívá v nevalidujících analyzátorech SAX (jako je ten, který používáme pro tento článek); processingInstruction () zvládá většinu věcí uvnitř a ?> oddělovače; a setDocumentLocator () je volitelně implementován analyzátory SAX, aby vám umožnil přístup k umístění událostí SAX v původním vstupním proudu. Tyto metody si můžete přečíst pomocí odkazů na rozhraní SAX v prostředcích.

Implementace všech metod v rozhraní může být zdlouhavá, pokud vás zajímá pouze chování jedné nebo dvou z nich. Balíček SAX obsahuje třídu s názvem HandlerBase to v podstatě nedělá nic, ale může vám pomoci využít pouze jednu nebo dvě z těchto metod. Podívejme se na tuto třídu podrobněji.

HandlerBase: Třída nedělat nic

Často vás zajímá implementace jedné nebo dvou metod v rozhraní a chcete, aby ostatní metody prostě nic nedělaly. Třída org.xml.sax.HandlerBase zjednodušuje provádění DocumentHandler rozhraní implementací všech metod rozhraní s těly nedělat nic. Pak místo implementace DocumentHandler, můžete podtřídu HandlerBasea přepsat pouze metody, které vás zajímají.

Řekněme například, že jste chtěli napsat program, který právě vytiskl název jakékoli básně ve formátu XML (například Vyhledávač titulů v seznamu 1). Můžete definovat nový DocumentHandler, podobně jako v seznamu 2 níže, tyto podtřídy HandlerBase, a přepíše pouze metody, které potřebujete. (Viz Zdroje pro soubor HTML z Vyhledávač titulů.)

012 / ** 013 * Třída SAX DocumentHandler, která vytiskne obsah prvku „TITLE“ 014 * vstupního dokumentu. 015 * / 016 veřejná třída TitleFinder rozšiřuje HandlerBase {017 boolean _isTitle = false; 018 public TitleFinder () {019 super (); 020} 021 / ** 022 * Tisk veškerého textu nalezeného uvnitř a  živel. 023 * / 024 public void characters (char [] chars, int iStart, int iLen) {025 if (_isTitle) {026 String sTitle = new String (chars, iStart, iLen); 027 System.out.println ("Název:" + sTitle); 028} 029} 030 / ** 031 * Označte konec prvku názvu. 032 * / 033 public void endElement (String element) {034 if (element.equals ("TITLE")) {035 _isTitle = false; 036} 037} 038 / ** 039 * Najít obsah titulů 040 * / 041 public static void main (String args []) {042 TitleFinder titleFinder = nový TitleFinder (); 043 try {044 Parser parser = ParserFactory.makeParser ("com.ibm.xml.parsers.SAXParser"); 045 parser.setDocumentHandler (titleFinder); 046 parser.parse (new InputSource (args [0])); 047} catch (výjimka ex) {048; // Dobře, takže někdy lenost * není * ctnost. 049} 050} 051 / ** 052 * Označit začátek prvku názvu 053 * / 054 public void startElement (String element, AttributeList attrlist) {055 if (element.equals ("TITLE")) {056 _isTitle = true; 057} 058} 

Výpis 2. TitleFinder: DocumentHandler odvozený z HandlerBase, který tiskne TITLE

Copyright cs.verticalshadows.com 2024

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