Programmēšana

XML kartēšana uz Java, 1. daļa

XML ir karsts. Tā kā XML ir pašraksturojošu datu forma, to var izmantot bagātīgu datu modeļu kodēšanai. XML lietderību ir viegli uztvert kā datu apmaiņas līdzekli starp ļoti atšķirīgām sistēmām. Datus var viegli atklāt vai publicēt kā XML no visu veidu sistēmām: mantotajām COBOL programmām, datu bāzēm, C ++ programmām utt.

TEKSTS:

TEXTBOX_HEAD: XML kartēšana uz Java: izlasiet visu sēriju!

  • 1. daļa - izmantojiet SAX API, lai XML dokumentus piesaistītu Java objektiem
  • 2. daļa - izveidojiet klases bibliotēku, kas izmanto SAX API, lai XML dokumentus piesaistītu Java objektiem

: END_TEXTBOX

Tomēr XML izmantošana sistēmu izveidošanai rada divas problēmas. Pirmkārt, lai gan XML ģenerēšana ir vienkārša procedūra, apgrieztā darbība, izmantojot XML datus no programmas, nav. Otrkārt, pašreizējās XML tehnoloģijas ir viegli nepareizi pielietojamas, un tas var atstāt programmētāju ar lēnu, atmiņu izsalkušu sistēmu. Patiešām, lielas atmiņas prasības un lēns ātrums var izrādīties problemātisks sistēmām, kuras kā galveno datu apmaiņas formātu izmanto XML.

Daži standarta rīki, kas pašlaik ir pieejami darbam ar XML, ir labāki nekā citi. Īpaši SAX API ir dažas svarīgas izpildlaika funkcijas veiktspējas jutīgam kodam. Šajā rakstā mēs izstrādāsim dažus modeļus SAX API lietošanai. Jūs varēsiet izveidot ātru XML-Java kartēšanas kodu ar minimālu atmiņas nospiedumu pat diezgan sarežģītām XML struktūrām (izņemot rekursīvās struktūras).

Šīs sērijas 2. daļā mēs aplūkosim SAX API piemērošanu rekursīvām XML struktūrām, kurās daži XML elementi apzīmē sarakstu sarakstus. Mēs izstrādāsim arī klases bibliotēku, kas pārvalda SAX API navigācijas aspektus. Šī bibliotēka vienkāršo XML kartēšanas koda rakstīšanu, pamatojoties uz SAX.

Kartēšanas kods ir līdzīgs koda sastādīšanai

Programmu rakstīšana, kurās tiek izmantoti XML dati, ir līdzīga kompilatora rakstīšanai. Tas ir, lielākā daļa kompilatoru pārveido avota kodu palaistā programmā trīs posmos. Pirmkārt, a leksers modulis grupē rakstzīmes vārdos vai žetonos, kurus sastādītājs atpazīst - procesu, kas pazīstams kā marķēšana. Otrais modulis, ko sauc par parsētājs, analizē žetonu grupas, lai atpazītu juridiskās valodas konstrukcijas. Visbeidzot, trešais modulis kodu ģenerators, ņem virkni juridiskās valodas, konstruē un ģenerē izpildāmo kodu. Dažreiz parsēšana un kodu ģenerēšana tiek sajaukti.

Lai XML datus izmantotu Java programmā, mums jāveic līdzīgs process. Pirmkārt, mēs analizējam katru rakstzīmi XML tekstā, lai atpazītu likumīgus XML marķierus, piemēram, sākuma tagus, atribūtus, beigu tagus un CDATA sadaļas.

Otrkārt, mēs pārbaudām, vai marķieri veido likumīgas XML konstrukcijas. Ja XML dokuments pilnībā sastāv no juridiskām konstrukcijām atbilstoši XML 1.0 specifikācijai, tas ir labi izveidota. Visvienkāršākajā līmenī mums jāpārliecinās, ka, piemēram, visiem tagiem ir atbilstoši sākuma un beigu tagi, un atribūti ir pareizi strukturēti sākuma tagā.

Turklāt, ja ir pieejams DTD, mums ir iespēja pārliecināties, ka parsēšanas laikā atrastie XML konstrukti ir likumīgi DTD ziņā, kā arī ir labi veidoti XML.

Visbeidzot, mēs izmantojam XML dokumentā esošos datus, lai paveiktu kaut ko noderīgu - es šo XML kartēšanu saucu Java.

XML parsētāji

Par laimi, ir pieejami komponenti - XML ​​parsētāji -, kas mums veic dažus no šiem kompilatoru saistītajiem uzdevumiem. XML parsētāji mums veic visus leksiskās analīzes un parsēšanas uzdevumus. Daudzi pašlaik pieejamie Java bāzes XML parsētāji atbalsta divus populārus parsēšanas standartus: SAX un DOM API.

Pieejamā XML parsētāja pieejamība var likt šķist, ka jūsu vietā ir paveikts, izmantojot XML Java. Patiesībā XML parsētāja izmantošana ir gatavs, tas ir iesaistīts uzdevums.

SAX un DOM API

SAX API ir balstīta uz notikumiem. XML parsētāji, kas ievieš SAX API, ģenerē notikumus, kas atbilst dažādām iezīmēm, kas atrodamas parsētajā XML dokumentā. Reaģējot uz šo SAX notikumu straumi Java kodā, varat rakstīt programmas, kuru pamatā ir XML dati.

DOM API ir objekta modeļa API. XML parsētāji, kas ievieš DOM, atmiņā izveido vispārēju objektu modeli, kas atspoguļo XML dokumenta saturu. Kad XML parsētājs ir pabeidzis parsēšanu, atmiņā ir DOM objektu koks, kas piedāvā informāciju gan par XML dokumenta struktūru, gan saturu.

DOM koncepcija ir izaugusi no HTML pārlūka pasaules, kur kopīgs dokumenta objekta modelis attēlo pārlūkprogrammā ielādēto HTML dokumentu. Pēc tam šis HTML DOM kļūst pieejams skriptu valodām, piemēram, JavaScript. HTML DOM šajā lietojumprogrammā ir bijis ļoti veiksmīgs.

DOM briesmas

No pirmā acu uzmetiena šķiet, ka DOM API ir daudz funkcijām bagātāka un tāpēc labāka nekā SAX API. Tomēr DOM ir nopietnas efektivitātes problēmas, kas var kaitēt lietojumam jutīgām lietojumprogrammām.

Pašreizējā XML parsētāju grupa, kas atbalsta DOM, ievieš atmiņā esošo objektu modeli, izveidojot daudz niecīgu objektu, kas attēlo DOM mezglus, kas satur tekstu vai citus DOM mezglus. Tas izklausās pietiekami dabiski, bet tam ir negatīva ietekme uz veiktspēju. Viena no dārgākajām operācijām Java ir jauns operators. Attiecīgi par katru jauns operatoram, kas izpildīts Java valodā, JVM atkritumu savācējam galu galā ir jāizņem objekts no atmiņas, kad nav saglabājušās atsauces uz objektu. DOM API mēdz patiešām izmest JVM atmiņas sistēmu ar daudzajiem mazajiem objektiem, kuri parasti tiek izmesti malā drīz pēc parsēšanas.

Vēl viena DOM problēma ir fakts, ka tas ielādē visu XML dokumentu atmiņā. Lieliem dokumentiem tas kļūst par problēmu. Atkal, tā kā DOM tiek ieviests tik daudz sīku objektu, atmiņas nospiedums ir pat lielāks nekā pats XML dokuments, jo JVM glabā dažus papildu baitus informācijas par visiem šiem objektiem, kā arī XML dokumenta saturu.

Tāpat satraucoši ir tas, ka daudzas Java programmas faktiski neizmanto DOM vispārīgo objektu struktūru. Tā vietā, tiklīdz DOM struktūra tiek ielādēta atmiņā, viņi kopē datus objekta modelī, kas raksturīgs konkrētam problēmu apgabalam - smalks, bet izšķērdīgs process.

Vēl viena smalka DOM API problēma ir tā, ka tai uzrakstītajam kodam divreiz jāpārbauda XML dokuments. Pirmais solis izveido DOM struktūru atmiņā, otrais atrod visus XML datus, kas interesē programmu. Daži kodēšanas stili var šķērsot DOM struktūru vairākas reizes vairāk, vienlaikus atrodot dažādus XML datu gabalus. Turpretī SAX kodēšanas stils mudina atrast un apkopot XML datus vienā piegājienā.

Dažas no šīm problēmām varētu risināt ar labāku datu struktūras dizainu, lai iekšēji pārstāvētu DOM objekta modeli. XML parsētājos nevar risināt tādus jautājumus kā vairāku apstrādes atļauju veicināšana un tulkošana starp vispārīgiem un specifiskiem objektu modeļiem.

SAX izdzīvošanai

Salīdzinot ar DOM API, SAX API ir pievilcīga pieeja. SAX nav vispārīga objekta modeļa, tāpēc tam nav atmiņas vai veiktspējas problēmu, kas saistītas ar jauns operators. Izmantojot SAX, nav vispārēja objekta modeļa, kuru varētu ignorēt, ja tā vietā plānojat izmantot noteiktu problēmu-domēna objekta modeli. Turklāt, tā kā SAX XML dokumentu apstrādā vienā piegājienā, tas prasa daudz mazāk apstrādes laika.

SAX patiešām ir daži trūkumi, taču tie galvenokārt ir saistīti ar programmētāju, nevis API izpildlaika veiktspēju. Apskatīsim dažus.

Pirmais trūkums ir konceptuāls. Programmētāji ir pieraduši pārvietoties, lai iegūtu datus; lai atrastu failu failu serverī, pārvietojieties, mainot direktorijus. Līdzīgi, lai iegūtu datus no datu bāzes, jūs rakstāt SQL vaicājumu vajadzīgajiem datiem. Izmantojot SAX, šis modelis ir apgriezts. Tas ir, jūs iestatāt kodu, kas klausās visu pieejamo XML datu gabalu sarakstu. Šis kods tiek aktivizēts tikai tad, kad tiek uzskaitīti interesanti XML dati. Sākumā SAX API šķiet nepāra, bet pēc kāda laika domāšana šādā apgrieztā veidā kļūst par otro dabu.

Otrais trūkums ir bīstamāks. Izmantojot SAX kodu, naivā pieeja “uzlauzīsim to” diezgan ātri atspēlēsies, jo SAX parsētājs izsmeļoši pārvietojas pa XML struktūru, vienlaikus piegādājot XML dokumentā saglabātos datus. Lielākā daļa cilvēku koncentrējas uz datu kartēšanas aspektu un atstāj novārtā navigācijas aspektu. Ja jūs tieši nenovērsiet SAX parsēšanas navigācijas aspektu, kods, kas SAX parsēšanas laikā seko atrašanās vietai XML struktūrā, tiks izplatīts un tam būs daudz smalku mijiedarbību. Šī problēma ir līdzīga tām, kas saistītas ar pārmērīgu atkarību no globālajiem mainīgajiem. Bet, ja jūs iemācāties pareizi strukturēt SAX kodu, lai tas nekļūtu apgrūtinošs, tas ir vienkāršāk nekā DOM API izmantošana.

Pamata SAX

Pašlaik ir divas SAX API publicētās versijas. Saviem piemēriem izmantosim 2. versiju (skatiet resursus). 2. versijā tiek izmantoti atšķirīgi klašu un metožu nosaukumi nekā 1. versijā, taču koda struktūra ir vienāda.

SAX ir API, nevis parsētājs, tāpēc šis kods ir vispārīgs XML parsētājiem. Lai palaistu piemērus, jums būs jāpiekļūst XML parsētājam, kas atbalsta SAX v2. Es izmantoju Apache Xerces parsētāju. (Skatiet resursus.) Pārskatiet sava parsētāja darba sākšanas rokasgrāmatu, lai uzzinātu vairāk par SAX parsētāja izsaukšanu.

SAX API specifikācija ir diezgan vienkārša. Iekļautas daudzas detaļas, bet tās galvenais uzdevums ir izveidot klasi, kas īsteno ContentHandler interfeiss, atzvanīšanas interfeiss, ko izmanto XML parsētāji, lai informētu jūsu programmu par SAX notikumiem, kā tie ir atrodami XML dokumentā.

SAX API ērti piegādā arī a DefaultHandler ieviešanas klase ContentHandler interfeiss.

Kad esat ieviesis ContentHandler vai pagarināja DefaultHandler, XML parsētājs ir jānovirza tikai konkrēta dokumenta parsēšanai.

Mūsu pirmais piemērs paplašina DefaultHandler lai katru SAX notikumu izdrukātu konsolē. Tas ļaus jums sajust, kādi SAX notikumi tiks ģenerēti un kādā secībā.

Lai sāktu, šeit ir XML dokumenta paraugs, kuru izmantosim savā pirmajā piemērā:

   Bobs Ņujorka 

Pēc tam mēs redzam pirmā piemēra XML kartēšanas koda avota kodu:

importēt org.xml.sax. *; importēt org.xml.sax.helpers. *; importēt java.io. *; public class 1. piemērs paplašina DefaultHandler {// DefaultHandler klases // ignorēšanas metodes //, lai iegūtu paziņojumu par SAX notikumiem. // // Visus pieejamos notikumus skatiet org.xml.sax.ContentHandler. // public void startDocument () izmet SAXException {System.out.println ("SAX Event: START DOCUMENT"); } public void endDocument () izmet SAXException {System.out.println ("SAX Event: END DOCUMENT"); } public void startElement (String namespaceURI, String localName, String qName, Atribūti attr) izmet SAXException {System.out.println ("SAX Event: START ELEMENT [" + localName + "]"); // Turklāt izdrukāsim atribūtus, ja // ir kādi ... domēnam (int i = 0; i <attr.getLength (); i ++) {System.out.println ("ATTRIBUTE:" + attr.getLocalName ( i) + "VALUE:" + attr.getValue (i)); }} public void endElement (String namespaceURI, String localName, String qName) izmet SAXException {System.out.println ("SAX Event: END ELEMENT [" + localName + "]"); } public void rakstzīmes (char [] ch, int start, int garums) met SAXException {System.out.print ("SAX Event: CHARACTERS ["); mēģiniet {OutputStreamWriter outw = new OutputStreamWriter (System.out); outw.write (ch, sākums, garums); outw.flush (); } catch (izņēmums e) {e.printStackTrace (); } System.out.println ("]"); } public static void main (String [] argv) {System.out.println ("1. piemērs SAX notikumi:"); mēģiniet {// Izveidot SAX 2 parsētāju ... XMLReader xr = XMLReaderFactory.createXMLReader (); // Iestatiet ContentHandler ... xr.setContentHandler (jauns piemērs1 ()); // Parsējiet failu ... xr.parse (new InputSource (new FileReader ("Example1.xml"))); } catch (izņēmums e) {e.printStackTrace (); }}} 

Visbeidzot, šeit ir produkcija, kas ģenerēta, izpildot pirmo piemēru ar mūsu XML dokumenta paraugu:

1. piemērs SAX notikumi: SAX notikums: START DOCUMENT SAX notikums: START ELEMENT [vienkāršs] ATTRIBUTE: datums VALUE: 7/7/2000 SAX Event: CHARACTERS [] SAX Event: START ELEMENT [name] SAX Event: CHARACTERS [Bob] SAX Event : END ELEMENT [nosaukums] SAX notikums: CHARACTERS [] SAX notikums: START ELEMENT [atrašanās vieta] SAX notikums: CHARACTERS [Ņujorka] SAX notikums: END ELEMENT [atrašanās vieta] SAX notikums: CHARACTERS [] SAX notikums: END ELEMENT [vienkāršs] SAX notikums: END DOCUMENT 

Kā redzat, SAX parsētājs izsauks atbilstošo ContentHandler metode katram SAX notikumam, ko tā atklāj XML dokumentā.

Sveika pasaule

Tagad, kad esam sapratuši SAX pamata modeli, mēs varam sākt darīt kaut ko nedaudz noderīgu: izvilkt vērtības no mūsu vienkāršā XML dokumenta un demonstrēt klasisko sveiki pasaules programmu.

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