Programiranje

Preslikava XML v Javo, 1. del

XML je vroč. Ker je XML oblika samoopisov podatkov, ga lahko uporabimo za kodiranje bogatih podatkovnih modelov. Pripomoček XML je enostavno videti kot medij za izmenjavo podatkov med zelo različnimi sistemi. Podatke je mogoče zlahka izpostaviti ali objaviti v obliki XML iz vseh vrst sistemov: starejših programov COBOL, baz podatkov, programov C ++ itd.

BESEDILO:

TEXTBOX_HEAD: Preslikava XML na Javo: preberite celotno serijo!

  • 1. del - Uporabite API SAX za preslikavo dokumentov XML v objekte Java
  • 2. del - Ustvarite knjižnico razredov, ki uporablja API SAX za preslikavo dokumentov XML v objekte Java

: END_TEXTBOX

Vendar uporaba XML za gradnjo sistemov predstavlja dva izziva. Prvič, čeprav je generiranje XML enostaven postopek, inverzna operacija z uporabo podatkov XML znotraj programa pa ne. Drugič, sedanje tehnologije XML je enostavno napačno uporabiti, kar lahko programerju pusti počasen, pomnilniško lačen sistem. Težke zahteve po pomnilniku in počasne hitrosti se lahko izkažejo za problematične za sisteme, ki uporabljajo XML kot svojo primarno obliko izmenjave podatkov.

Nekatera standardna orodja, ki so trenutno na voljo za delo z XML, so boljša od drugih. API SAX ima zlasti nekaj pomembnih funkcij za izvajanje kode, ki je občutljiva na delovanje. V tem članku bomo razvili nekaj vzorcev za uporabo API-ja SAX. Ustvarili boste lahko hitro preslikavno kodo XML-Java z minimalnim odtisom pomnilnika, tudi za dokaj zapletene strukture XML (z izjemo rekurzivnih struktur).

V 2. delu te serije bomo obravnavali uporabo API-ja SAX za rekurzivne strukture XML, v katerih nekateri elementi XML predstavljajo sezname seznamov. Razvili bomo tudi knjižnico razredov, ki bo upravljala navigacijske vidike API-ja SAX. Ta knjižnica poenostavlja pisanje preslikave XML na osnovi SAX.

Karta za preslikavo je podobna sestavi kode

Pisanje programov, ki uporabljajo podatke XML, je podobno pisanju prevajalnika. To pomeni, da večina prevajalnikov pretvori izvorno kodo v izvedljiv program v treh korakih. Najprej, a lexer modul združuje znake v besede ali žetone, ki jih prevajalnik prepozna - postopek, znan kot tokeniziranje. Drugi modul, imenovan razčlenjevalnik, analizira skupine žetonov z namenom prepoznavanja pravnih jezikovnih konstruktov. Zadnji, tretji modul, generator kod, vzame nabor pravnih jezikovnih konstrukcij in ustvari izvršljivo kodo. Včasih se razčlenjevanje in generiranje kode pomešata.

Za uporabo podatkov XML v programu Java moramo opraviti podoben postopek. Najprej analiziramo vsak znak v besedilu XML, da prepoznamo zakonite žetone XML, kot so začetne oznake, atributi, končne oznake in odseki CDATA.

Drugič, preverimo, ali žetoni tvorijo zakonite konstrukcije XML. Če je dokument XML v celoti sestavljen iz pravnih konstruktov po specifikaciji XML 1.0, je dobro oblikovan. Na najosnovnejši ravni moramo zagotoviti, da imajo na primer vsa označevanja ujemajoče se začetne in zaključne oznake in da so atributi pravilno strukturirani v uvodni oznaki.

Če je na voljo DTD, lahko zagotovimo, da so konstrukcije XML, ki jih najdemo med razčlenjevanjem, zakonite v smislu DTD in da so tudi dobro oblikovan XML.

Na koncu uporabimo podatke iz dokumenta XML, da dosežemo nekaj koristnega - temu pravim preslikava XML v Javo.

Razčlenjevalniki XML

Na srečo obstajajo gotove komponente - razčlenjevalniki XML, ki za nas izvajajo nekatera od teh nalog, povezanih s prevajalnikom. Razčlenjevalniki XML za nas obravnavajo vse naloge leksikalne analize in razčlenjevanja. Številni trenutno razpoložljivi razčlenjevalniki XML, ki temeljijo na Javi, podpirajo dva priljubljena standarda razčlenjevanja: API-ja SAX in DOM.

Zaradi razpoložljivosti razčlenjevalnika XML, ki je na voljo, se lahko zdi, da je bil težaven del uporabe XML v Javi narejen za vas. V resnici je uporaba rednega razčlenjevalnika XML vključena naloga.

API-ji SAX in DOM

API SAX temelji na dogodkih. Razčlenjevalniki XML, ki izvajajo API SAX, ustvarjajo dogodke, ki ustrezajo različnim funkcijam, ki jih najdete v razčlenjenem dokumentu XML. Če se odzovete na ta tok dogodkov SAX v kodo Java, lahko pišete programe, ki temeljijo na podatkih, ki temeljijo na XML.

DOM API je API, ki temelji na objektnem modelu. Razčlenjevalniki XML, ki izvajajo DOM, v pomnilniku ustvarijo generični objektni model, ki predstavlja vsebino dokumenta XML. Ko je razčlenjevalnik XML dokončal razčlenjevanje, pomnilnik vsebuje drevo objektov DOM, ki ponuja informacije o strukturi in vsebini dokumenta XML.

Koncept DOM je zrasel iz sveta brskalnikov HTML, kjer skupni objektni model dokumenta predstavlja dokument HTML, naložen v brskalnik. Ta HTML DOM nato postane na voljo za skriptne jezike, kot je JavaScript. HTML DOM je bil zelo uspešen v tej aplikaciji.

Nevarnosti DOM-a

Na prvi pogled se zdi, da je API DOM bolj bogat in zato boljši od API-ja SAX. Vendar ima DOM resne težave z učinkovitostjo, ki lahko škodujejo aplikacijam, občutljivim na delovanje.

Trenutna skupina razčlenjevalnikov XML, ki podpirajo DOM, izvaja objektni model v pomnilniku z ustvarjanjem številnih drobnih predmetov, ki predstavljajo vozlišča DOM, ki vsebujejo besedilo ali druga vozlišča DOM. To se sliši dovolj naravno, vendar ima negativne posledice za uspešnost. Ena najdražjih operacij v Javi je novo operater. Ustrezno, za vsakega novo operater, izveden v Javi, mora zbiralnik smeti JVM sčasoma odstraniti predmet iz pomnilnika, ko na objekt ne ostane nobena referenca. API DOM ponavadi resnično uniči pomnilniški sistem JVM s številnimi majhnimi predmeti, ki jih običajno vržejo stran kmalu po razčlenjevanju.

Druga težava z DOM je dejstvo, da naloži celoten dokument XML v pomnilnik. Pri velikih dokumentih to postane problem. Ker je v DOM implementirano toliko drobnih predmetov, je odtis pomnilnika celo večji od samega dokumenta XML, ker JVM shrani nekaj dodatnih bajtov informacij o vseh teh objektih, pa tudi o vsebini dokumenta XML.

Zaskrbljujoče je tudi, da številni programi Java dejansko ne uporabljajo generične objektne strukture DOM-a. Namesto tega, takoj ko se struktura DOM naloži v pomnilnik, kopirajo podatke v objektni model, specifičen za določeno domeno težave - subtilen, a potraten postopek.

Druga prefinjena težava za DOM API je, da mora zanj napisana koda dvakrat skenirati dokument XML. Prvi prehod ustvari strukturo DOM v pomnilniku, drugi poišče vse podatke XML, ki jih program zanima. Nekateri slogi kodiranja lahko strukturo DOM prečkajo večkrat, medtem ko locirajo različne koščke podatkov XML. Nasprotno pa slog kodiranja SAX spodbuja iskanje in zbiranje podatkov XML v enem prehodu.

Nekatera od teh vprašanj bi lahko rešili z boljšo zasnovo strukture podatkovne strukture, da bi interno predstavljali objektni model DOM. Težav, kot sta spodbujanje večkratnih prehodov obdelave in prevajanje med generičnimi in določenimi objektnimi modeli, ni mogoče obravnavati znotraj razčlenjevalnikov XML.

SAX za preživetje

V primerjavi z API-jem DOM je API SAX privlačen pristop. SAX nima generičnega objektnega modela, zato nima težav s pomnilnikom ali zmogljivostjo, povezanimi z zlorabo novo operater. In pri SAX ni generičnega objektnega modela, ki bi ga prezrli, če namesto tega nameravate uporabiti določen objektni model s problematično domeno. Poleg tega, ker SAX dokument XML obdela v enem prehodu, zahteva veliko manj časa za obdelavo.

SAX sicer ima nekaj pomanjkljivosti, vendar so večinoma povezane s programerjem in ne z zmogljivostjo API-ja med izvajanjem. Poglejmo si nekaj.

Prva pomanjkljivost je konceptualna. Programerji so navajeni krmariti po podatkih; če želite poiskati datoteko na datotečnem strežniku, krmarite s spreminjanjem imenikov. Podobno za pridobivanje podatkov iz baze podatkov napišete poizvedbo SQL za podatke, ki jih potrebujete. Pri SAX je ta model obrnjen. To pomeni, da nastavite kodo, ki posluša seznam vseh razpoložljivih podatkov XML, ki so na voljo. Ta koda se aktivira šele, ko so navedeni zanimivi podatki XML. Sprva se zdi SAX API čuden, a čez nekaj časa razmišljanje na ta obrnjen način postane druga narava.

Druga pomanjkljivost je bolj nevarna. Pri kodi SAX se bo naivni pristop "hack it heck" dokaj hitro obrnil, ker razčlenjevalnik SAX izčrpno krmari po strukturi XML, hkrati pa podaja podatke, shranjene v dokumentu XML. Večina ljudi se osredotoča na vidik preslikave podatkov in zanemarja navigacijski vidik. Če ne boste neposredno obravnavali navigacijskega vidika razčlenjevanja SAX, se bo koda, ki bo spremljala lokacijo v strukturi XML med razčlenjevanjem SAX, razširila in imela veliko prefinjenih interakcij. Ta problem je podoben tistim, ki so povezani s preveliko odvisnostjo od globalnih spremenljivk. Če pa se naučite pravilno strukturirati kodo SAX, da ne bo postala okorna, je to bolj preprosto kot uporaba API-ja DOM.

Osnovni SAX

Trenutno sta objavljeni dve različici API-ja SAX. Za naše primere bomo uporabili različico 2 (glejte Vire). Različica 2 uporablja drugačna imena razredov in metod kot različica 1, vendar je struktura kode enaka.

SAX je API, ne razčlenjevalnik, zato je ta koda generična za razčlenjevalnike XML. Če želite, da se primeri zaženejo, boste morali dostopati do razčlenjevalnika XML, ki podpira SAX v2. Uporabljam razčlenjevalnik Apache Xerces. (Glejte Vire.) V podrobnih navodilih za priklic razčlenjevalnika SAX si oglejte vodnik za začetek razčlenjevanja.

Specifikacija SAX API je precej preprosta. Vključuje veliko podrobnosti, vendar je njegova glavna naloga ustvariti razred, ki izvaja ContentHandler vmesnik, vmesnik povratnega klica, ki ga uporabljajo razčlenjevalniki XML za obveščanje vašega programa o dogodkih SAX, kot jih najdete v dokumentu XML.

API SAX tudi priročno dobavlja a DefaultHandler izvedbeni razred za ContentHandler vmesnik.

Ko ste izvedli ContentHandler ali podaljšali DefaultHandler, za razčlenitev določenega dokumenta potrebujete le razčlenjevalnik XML.

Naš prvi primer razširja DefaultHandler za tiskanje vsakega dogodka SAX na konzolo. Tako boste dobili občutek, kateri dogodki SAX bodo ustvarjeni in v kakšnem vrstnem redu.

Za začetek je tukaj vzorec dokumenta XML, ki ga bomo uporabili v prvem primeru:

   Bob New York 

Nato vidimo izvorno kodo za preslikavo XML prvega primera:

uvoz org.xml.sax. *; uvoz org.xml.sax.helpers. *; uvoz java.io. *; javni razred Example1 razširi DefaultHandler {// Preglasi metode razreda DefaultHandler //, da pridobi obvestilo o dogodkih SAX. // // Glejte org.xml.sax.ContentHandler za vse razpoložljive dogodke. // javna void startDocument () vrže SAXException {System.out.println ("Dogodek SAX: ZAČNI DOKUMENT"); } public void endDocument () vrže SAXException {System.out.println ("SAX dogodek: END DOCUMENT"); } public void startElement (String namespaceURI, String localName, String qName, Attributes attr) vrže SAXException {System.out.println ("SAX Event: START ELEMENT [" + localName + "]"); // Prav tako natisnimo atribute, če // obstajajo ... for (int i = 0; i <attr.getLength (); i ++) {System.out.println ("ATTRIBUTE:" + attr.getLocalName ( i) + "VREDNOST:" + attr.getValue (i)); }} public void endElement (String namespaceURI, String localName, String qName) vrže SAXException {System.out.println ("SAX Dogodek: END ELEMENT [" + localName + "]"); } javni void znaki (char [] ch, int start, int length) vrže SAXException {System.out.print ("SAX Dogodek: KARAKTERJI" "); poskusite {OutputStreamWriter outw = nov OutputStreamWriter (System.out); outw.write (ch, začetek, dolžina); outw.flush (); } catch (izjema e) {e.printStackTrace (); } System.out.println ("]"); } public static void main (String [] argv) {System.out.println ("Example1 SAX Events:"); poskusite {// Ustvari razčlenjevalnik SAX 2 ... XMLReader xr = XMLReaderFactory.createXMLReader (); // Nastavimo ContentHandler ... xr.setContentHandler (nov Primer1 ()); // Razčleni datoteko ... xr.parse (nov InputSource (nov FileReader ("Example1.xml"))); } catch (izjema e) {e.printStackTrace (); }}} 

Na koncu je tu rezultat, ustvarjen z izvajanjem prvega primera z našim vzorčnim dokumentom XML:

Primer1 SAX dogodki: SAX dogodek: START DOKUMENT SAX dogodek: START ELEMENT [preprost] ATTRIBUTE: datum VREDNOST: 7/7/2000 SAX dogodek: CHARACTERS [] SAX dogodek: START ELEMENT [ime] SAX dogodek: CHARACTERS [Bob] SAX dogodek : END ELEMENT [ime] SAX dogodek: KARAKTERI [] SAX dogodek: START ELEMENT [lokacija] SAX dogodek: CHARACTERS [New York] SAX dogodek: END ELEMENT [lokacija] SAX dogodek: CHARACTERS [] SAX dogodek: END ELEMENT [preprosto] SAX dogodek: KONČNI DOKUMENT 

Kot lahko vidite, bo razčlenjevalnik SAX poklical ustreznega ContentHandler za vsak dogodek SAX, ki ga odkrije v dokumentu XML.

Pozdravljen, svet

Zdaj, ko razumemo osnovni vzorec SAX, lahko začnemo nekaj koristnega: izvlečemo vrednosti iz našega preprostega dokumenta XML in predstavimo klasični program hello world.

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