Programmering

Programmering af XML i Java, del 1

Så du forstår (mere eller mindre) hvordan du repræsenterer dine data i XML, og du er interesseret i at bruge XML til at løse mange af dine datastyringsproblemer. Alligevel er du ikke sikker på, hvordan du bruger XML med dine Java-programmer.

TEXTBOX: TEXTBOX_HEAD: Programmering af XML i Java: Læs hele serien!

  • Del 1. Brug Simple API til XML (SAX) til at behandle XML i Java nemt
  • Del 2. Lær om SAX- og XML-validering gennem illustrative eksempler
  • Del 3. DOMINERING: Tag kontrol over strukturerede dokumenter med dokumentobjektmodellen

: END_TEXTBOX

Denne artikel er en opfølgning på min indledende artikel, "XML for den absolutte begynder", i april 1999-udgaven af JavaWorld (se afsnittet Ressourcer nedenfor for URL). Denne artikel beskrev XML; Jeg vil nu bygge videre på denne beskrivelse og vise i detaljer, hvordan man opretter en applikation, der bruger Simple API til Java (SAX), en let og kraftfuld standard Java API til behandling af XML.

Eksempelkoden, der bruges her, bruger SAX API til at læse en XML-fil og skabe en nyttig struktur af objekter. Når du er færdig med denne artikel, er du klar til at oprette dine egne XML-baserede applikationer.

Dyden til dovenskab

Larry Wall, skør genial skaber af Perl (det næststørste programmeringssprog, der findes), har udtalt, at dovenskab er en af ​​de "tre store dyder" hos en programmør (de to andre er utålmodighed og hubris). Dovenskab er en dyd, fordi en doven programmør vil gå i næsten enhver længde for at undgå arbejde, selv gå så langt som at skabe generelle, genanvendelige programmeringsrammer, der kan bruges gentagne gange. Oprettelse af sådanne rammer medfører meget arbejde, men den sparede tid på fremtidige opgaver udgør mere end den oprindelige investering. De bedste rammer lader programmører gøre fantastiske ting med lidt eller intet arbejde - og derfor er dovenskab dydig.

XML er en aktiveringsteknologi for den dydige (dovne) programmør. En grundlæggende XML-parser gør meget arbejde for programmøren, genkender tokens, oversætter kodede tegn, håndhæver regler for XML-filstruktur, kontrollerer gyldigheden af ​​nogle dataværdier og foretager opkald til applikationsspecifik kode, hvor det er relevant. Faktisk har tidlig standardisering, kombineret med en stærkt konkurrencepræget markedsplads, produceret snesevis af frit tilgængelige implementeringer af standard XML-parsere på mange sprog, herunder C, C ++, Tcl, Perl, Python og selvfølgelig Java.

SAX API er en af ​​de enkleste og mest lette grænseflader til håndtering af XML. I denne artikel bruger jeg IBMs XML4J-implementering af SAX, men da API'en er standardiseret, kan din applikation erstatte enhver pakke, der implementerer SAX.

SAX er en begivenhedsbaseret API, der fungerer efter tilbagekaldsprincippet. En applikationsprogrammerer opretter typisk en SAX Parser objekt, og videregiv det både input XML og a dokumenthåndtering, der modtager tilbagekald til SAX-begivenheder. SAX Parser konverterer dens input til en strøm af begivenheder svarende til strukturelle træk ved input, såsom XML-tags eller tekstblokke. Efterhånden som hver begivenhed opstår, sendes den til den passende metode til en programmørdefineret dokumenthåndterer, der implementerer tilbagekaldsgrænsefladen org.xml.sax.DocumentHandler. Metoderne i denne håndteringsklasse udfører den applikationsspecifikke funktionalitet under analysen.

Forestil dig f.eks., At en SAX-parser modtager et dokument, der indeholder det lille XML-dokument, der vises i liste 1 nedenfor. (Se ressourcer til XML-filen.)

 Ogden Nash Fleas Adam Had 'em. 

Liste 1. XML, der repræsenterer et kort digt

Når SAX-parseren støder på tag kalder det det brugerdefinerede DocumentHandler.startElement () med strengen DIGT som et argument. Du implementerer startElement () metode til at gøre hvad applikationen er beregnet til at gøre, når en DIGT begynder. Strømmen af ​​begivenheder og resulterende opkald til stykket XML ovenfor vises i tabel 1 nedenfor.

Tabel 1. Sekvensen af ​​tilbagekald, som SAX producerer under parsing af liste 1
Element fundetParser-tilbagekald
{Begyndelse af dokument}startDokument ()
startElement ("POEM", {AttributeList})
"\ n"tegn ("\ n ...", 6, 1)
startElement ("AUTHOR", {AttributeList})
"Ogden Nash"tegn ("\ n ...", 15, 10)
endElement ("FORFATTER")
"\ n"tegn ("\ n ...", 34, 1)
startElement ("TITLE", {AttributeList})
"Lopper"tegn ("\ n ...", 42, 5)
endElement ("TITLE")
"\ n"tegn ("\ n ...", 55, 1)
startElement ("LINE", {AttributeList})
"Adam"tegn ("\ n ...", 62, 4)
endElement ("LINE")
startElement ("LINE", {AttributeList})
"Havde dem."tegn ("\ n ...", 67, 8)
endElement ("LINE")
"\ n"tegn ("\ n ...", 82, 1)
endElement ("DIG")
{Slut på dokument}endDocument ()

Du opretter en klasse, der implementeres DocumentHandler for at svare på begivenheder, der opstår i SAX-parseren. Disse begivenheder er ikke Java-begivenheder, som du måske kender dem fra Abstract Windowing Toolkit (AWT). De er forhold, som SAX-parseren registrerer, når den parses, såsom starten på et dokument eller forekomsten af ​​et lukkemærke i inputstrømmen. Da hver af disse betingelser (eller begivenheder) opstår, kalder SAX den metode, der svarer til betingelsen i dens DocumentHandler.

Så nøglen til at skrive programmer, der behandler XML med SAX, er at finde ud af, hvad DocumentHandler skal gøre som svar på en strøm af metodetilbagekald fra SAX. SAX-parseren tager sig af al mekanikken til at identificere tags, erstatte enhedsværdier og så videre, hvilket giver dig frihed til at koncentrere dig om den applikationsspecifikke funktionalitet, der bruger de data, der er kodet i XML.

Tabel 1 viser kun begivenheder, der er knyttet til elementer og tegn. SAX inkluderer også faciliteter til håndtering af andre strukturelle funktioner i XML-filer, såsom enheder og behandlingsinstruktioner, men disse er uden for denne artikels anvendelsesområde.

Den kloge læser vil bemærke, at et XML-dokument kan repræsenteres som et træ af indtastede objekter, og at rækkefølgen af ​​strømmen af ​​begivenheder, der præsenteres for DocumentHandler svarer til en rækkefølge i rækkefølge efter dybden af ​​dokumenttræet. (Det er ikke vigtigt at forstå dette punkt, men konceptet med et XML-dokument som en treddatastruktur er nyttigt i mere sofistikerede typer dokumentbehandling, som vil blive dækket af senere artikler i denne serie.)

Nøglen til at forstå, hvordan man bruger SAX, er forståelse af DocumentHandler interface, som jeg vil diskutere næste.

Tilpas parseren med org.xml.sax.DocumentHandler

Siden DocumentHandler interface er så centralt for behandling af XML med SAX, det er umagen værd at forstå, hvad metoderne i grænsefladen gør. Jeg dækker de væsentlige metoder i dette afsnit og springer dem over, der beskæftiger sig med mere avancerede emner. Husk, DocumentHandler er en grænseflade, så de metoder, jeg beskriver, er metoder, som du vil implementere for at håndtere applikationsspecifik funktionalitet, når den tilsvarende begivenhed opstår.

Dokument initialisering og oprydning

For hvert parsede dokument kalder SAX XML-parseren DocumentHandler interface metoder startDokument () (kaldes inden behandlingen begynder) og endDocument () (kaldes efter behandling er afsluttet). Du kan bruge disse metoder til at initialisere din DocumentHandler at forberede det til modtagelse af begivenheder og til at rydde op eller producere output, når parsingen er afsluttet. endDocument () er især interessant, da det kun kaldes, hvis et inputdokument er blevet parset med succes. Hvis den Parser genererer en fatal fejl, den afbryder simpelthen begivenhedsstrømmen og stopper parsing, og endDocument () kaldes aldrig.

Behandler tags

SAX-parseren kalder startElement () når det støder på et åbent tag, og endElement () når det støder på et tæt mærke. Disse metoder indeholder ofte den kode, der udfører størstedelen af ​​arbejdet, mens man analyserer en XML-fil. startElement ()Det første argument er en streng, som er tagnavnet på det element, der er stødt på. Det andet argument er et objekt af typen Attributliste, en grænseflade defineret i pakke org.xml.sax der giver sekventiel eller tilfældig adgang til elementattributter efter navn. (Du har utvivlsomt set attributter før i HTML; i linjen

, GRÆNSE er en attribut, hvis værdi er "1"). Da Listing 1 ikke indeholder attributter, vises de ikke i tabel 1. Du kan se eksempler på attributter i eksempelapplikationen senere i denne artikel.

Da SAX ikke giver nogen oplysninger om sammenhængen med de elementer, den møder (det vises indeni i liste 1 ovenfor, for eksempel) er det op til dig at levere disse oplysninger. Applikationsprogrammerere bruger ofte stakke i startElement () og endElement (), skubber objekter på en stak, når et element starter, og springer dem ud af stakken, når elementet slutter.

Behandle tekstblokke

Det tegn () metode angiver tegnindhold i XML-dokumentet - tegn, der med andre ord ikke vises i et XML-tag. Denne metodes underskrift er lidt underligt. Det første argument er et array af bytes, det andet er et indeks i det array, der indikerer det første tegn i området, der skal behandles, og det tredje argument er længden af ​​tegnområdet.

Det ser ud til, at en lettere API simpelthen ville have bestået en Snor objekt, der indeholder dataene, men tegn () blev defineret på denne måde af effektivitetshensyn. Parseren har ingen måde at vide, om du vil bruge tegnene eller ej, så når parseren parser sin inputbuffer, sender den en henvisning til bufferen og indekserne for den streng, den ser på, i tillid til at du vil konstruere din egen Snor hvis du vil have en. Det er lidt mere arbejde, men det giver dig mulighed for at beslutte, om du vil pådrage dig omkostningerne ved Snor konstruktion for indholdsstykker i en XML-fil.

Det tegn () metoden håndterer både almindeligt tekstindhold og indhold i CDATA-sektioner, som bruges til at forhindre, at blokke af bogstavelig tekst bliver parset af en XML-parser.

Andre metoder

Der er tre andre metoder i DocumentHandler grænseflade: ignorableWhitespace (), bearbejdningsinstruktion ()og setDocumentLocator (). ignorableWhitespace () rapporterer forekomster af hvidt rum og er normalt ubrugt i ikke-validerende SAX-parsere (som den, vi bruger til denne artikel); bearbejdningsinstruktion () håndterer de fleste ting indeni og ?> afgrænsere og setDocumentLocator () er valgfrit implementeret af SAX-parsere for at give dig adgang til placeringen af ​​SAX-begivenheder i den oprindelige inputstrøm. Du kan læse om disse metoder ved at følge linkene til SAX-grænsefladerne i Resources.

Implementering af alle metoderne i en grænseflade kan være kedelig, hvis du kun er interesseret i en eller to af dem. SAX-pakken inkluderer en klasse kaldet HandlerBase der dybest set ikke gør noget, men kan hjælpe dig med at udnytte kun en eller to af disse metoder. Lad os undersøge denne klasse mere detaljeret.

HandlerBase: En gør-ingenting-klasse

Ofte er du kun interesseret i at implementere en eller to metoder i en grænseflade og vil have, at de andre metoder simpelthen ikke gør noget. Klassen org.xml.sax.HandlerBase forenkler implementeringen af ​​programmet DocumentHandler grænseflade ved at implementere alle grænseflades metoder med gør-intet-organer. Derefter i stedet for at implementere DocumentHandler, kan du underklasse HandlerBase, og tilsidesæt kun de metoder, der interesserer dig.

Sig for eksempel, at du ville skrive et program, der netop udskrev titlen på ethvert XML-formateret digt (som f.eks TitleFinder i liste 1). Du kan definere et nyt DocumentHandler, som den i liste 2 nedenfor, der underklasser HandlerBaseog tilsidesætter kun de metoder, du har brug for. (Se ressourcer for en HTML-fil af TitleFinder.)

012 / ** 013 * SAX DocumentHandler-klasse, der udskriver indholdet af "TITLE" -element 014 * i et inputdokument. 015 * / 016 public class TitleFinder udvider HandlerBase {017 boolean _isTitle = false; 018 offentlig TitleFinder () {019 super (); 020} 021 / ** 022 * Udskriv al tekst, der findes i en  element. 023 * / 024 offentlige ugyldige tegn (char [] tegn, int iStart, int iLen) {025 hvis (_isTitle) {026 String sTitle = ny streng (tegn, iStart, iLen); 027 System.out.println ("Titel:" + sTitle); 028} 029} 030 / ** 031 * Marker titelelementets afslutning. 032 * / 033 public void endElement (String element) {034 if (element.equals ("TITLE")) {035 _isTitle = false; 036} 037} 038 / ** 039 * Find indhold af titler 040 * / 041 offentlig statisk ugyldig hoved (String args []) {042 TitleFinder titleFinder = new TitleFinder (); 043 prøv {044 Parser parser = ParserFactory.makeParser ("com.ibm.xml.parsers.SAXParser"); 045 parser.setDocumentHandler (titleFinder); 046 parser.parse (ny InputSource (args [0])); 047} fangst (undtagelse ex) {048; // OK, så nogle gange er dovenskab * ikke en dyd. 049} 050} 051 / ** 052 * Marker titelelementets start 053 * / 054 public void startElement (String element, AttributeList attrlist) {055 if (element.equals ("TITLE")) {056 _isTitle = true; 057} 058} 

Liste 2. TitleFinder: En DocumentHandler afledt af HandlerBase, der udskriver TITLE'er

Copyright verticalshadows.com 2021