Programavimas

XML dokumentų apdorojimas „Java“ sistemoje naudojant „XPath“ ir „XSLT“

Išplėstinė žymėjimo kalba (XML) šiuo metu yra tikrai viena iš karščiausių technologijų. Nors žymėjimo kalbų samprata nėra nauja, XML atrodo ypač patraukli „Java“ ir interneto programuotojams. „Java“ API XML analizavimui (JAXP; žr. „Resursai“), neseniai apibrėžta per „Java“ bendruomenės procesą, žada suteikti bendrą sąsają, kad būtų galima pasiekti XML dokumentus. W3C apibrėžė vadinamąjį „Document Object Model“ (DOM), kuris suteikia standartinę sąsają darbui su XML dokumentu medžių hierarchijoje, o „Simple API for XML“ (SAX) leidžia programai nuosekliai išanalizuoti XML dokumentą remiantis pagal įvykių tvarkymo modelį. Abu šie standartai (SAX yra de facto standartas) papildo JAXP. Kartu šios trys API suteikia pakankamą palaikymą tvarkant XML dokumentus „Java“ sistemoje, o daugybė knygų rinkoje aprašo jų naudojimą.

Šiame straipsnyje pristatomas XML dokumentų tvarkymo būdas, viršijantis standartines „Java“ API, skirtas manipuliuoti XML. Pamatysime, kad daugeliu atvejų „XPath“ ir „XSLT“ suteikia paprastesnius ir elegantiškesnius būdus, kaip išspręsti programų problemas. Kai kuriuose paprastuose pavyzdžiuose palyginsime gryną „Java“ / XML sprendimą su „XPath“ ir (arba) „XSLT“.

Tiek XSLT, tiek „XPath“ yra „Extensible Stylesheet Language“ (XSL) specifikacijos dalis (žr. Ištekliai). XSL susideda iš trijų dalių: pačios XSL kalbos specifikacijos, XSL transformacijų (XSLT) ir XML kelio kalbos (XPath). XSL yra kalba, skirta XML dokumentams transformuoti; jame pateikiamas apibrėžimas - „Objektų formatavimas“ - kaip XML dokumentus galima formatuoti pateikimui. XSLT nurodo žodyną, kaip vieną XML dokumentą paversti kitu. Galite laikyti XSLT kaip XSL atėmus objektų formatavimą. „XPath“ kalba skirta tam tikroms XML dokumentų dalims ir yra skirta naudoti iš XSLT stiliaus lapo.

Laikoma, kad šiame straipsnyje esate susipažinę su XML ir XSLT pagrindais, taip pat su DOM API. (Informacijos ir pamokų šiomis temomis ieškokite šaltiniuose.)

Pastaba: Šio straipsnio kodo pavyzdžiai buvo sudaryti ir išbandyti naudojant „Apache Xerces XML“ analizatorių ir „Apache Xalan XSL“ procesorių (žr. Ištekliai).

Problema

Daugelyje straipsnių ir straipsnių, kuriuose kalbama apie XML, teigiama, kad tai yra puikus įrankis norint įgyvendinti gerą projektavimo praktiką atliekant žiniatinklio programavimą: „Model-View-Controller“ modelį (MVC) arba, paprasčiau tariant, programos duomenų atskyrimą nuo pateikimo duomenų . Jei programos duomenys suformatuoti XML, juos galima lengvai susieti - paprastai servlete ar „Java ServerPage“ -, tarkime, HTML šablonuose, naudojant XSL stiliaus lapą.

Tačiau XML gali padaryti daug daugiau nei tik padėti atskleisti modelio vaizdą programos priekyje. Šiuo metu pastebime vis plačiau naudojamus komponentus (pavyzdžiui, komponentus, sukurtus naudojant EJB standartą), kuriuos galima naudoti programoms surinkti, taip padidinant kūrėjų produktyvumą. Komponentų pakartotinį naudojimą galima pagerinti formatuojant duomenis, kuriuos komponentai tvarko standartiniu būdu. Iš tikrųjų galime tikėtis pamatyti vis daugiau publikuotų komponentų, kurie naudoja XML savo sąsajoms apibūdinti.

Kadangi XML formato duomenys yra neutralūs kalbai, jie tampa tinkami tais atvejais, kai tam tikros programos paslaugos klientas nėra žinomas arba kai jie neturi turėti jokių priklausomybių nuo serverio. Pavyzdžiui, B2B aplinkoje gali būti nepriimtina, kad dvi šalys, keisdamosi duomenimis, turi priklausomybę nuo konkrečių „Java“ objektų sąsajų. Naujos technologijos, tokios kaip paprastas objekto prieigos protokolas (SOAP) (žr. Ištekliai), atitinka šiuos reikalavimus.

Visi šie atvejai turi vieną bendrą bruožą: duomenys saugomi XML dokumentuose, todėl programa turi jais manipuliuoti. Pavyzdžiui, programa, naudojanti įvairius skirtingų tiekėjų komponentus, greičiausiai turės pakeisti (XML) duomenų struktūrą, kad ji atitiktų programos poreikius arba atitiktų nurodytą standartą.

Kodas, parašytas naudojant aukščiau minėtas „Java“ API, tikrai tai padarytų. Be to, yra vis daugiau prieinamų įrankių, kuriais galite XML dokumentą paversti „JavaBean“ ir atvirkščiai, o tai palengvina duomenų tvarkymą iš „Java“ programos. Tačiau daugeliu atvejų programa ar bent jos dalis paprasčiausiai apdoroja vieną ar kelis XML dokumentus kaip įvestį ir paverčia juos kitu XML formatu kaip išvestimi. Stiliaus lapų naudojimas tokiais atvejais yra perspektyvi alternatyva, kaip pamatysime vėliau šiame straipsnyje.

Norėdami rasti mazgus XML dokumente, naudokite „XPath“

Kaip minėta aukščiau, XPath kalba naudojama norint rasti tam tikras XML dokumento dalis. Kaip toks, jis skirtas naudoti XSLT stilių lape, tačiau niekas netrukdo jo naudoti „Java“ programoje, kad išvengtume ilgos iteracijos per DOM elementų hierarchiją. Iš tiesų, galime leisti XSLT / XPath procesoriui atlikti darbą už mus. Pažvelkime, kaip tai veikia.

Tarkime, kad mes turime programos scenarijų, kai vartotojui pateikiamas šaltinio XML dokumentas (galbūt po to, kai jį apdoroja stiliaus lapas). Vartotojas atnaujina duomenis ir, norėdamas sutaupyti tinklo pralaidumą, atgal į programą siunčia tik atnaujintus įrašus. Programa ieško XML fragmento šaltinio dokumente, kurį reikia atnaujinti, ir pakeičia jį naujais duomenimis.

Mes sukursime nedidelį pavyzdį, kuris padės suprasti įvairias galimybes. Šiame pavyzdyje manome, kad programa nagrinėja adreso įrašus adresų knyga. Pavyzdys adresų knyga dokumentas atrodo taip:

  John Smith 250 18th Ave SE Rochester MN 55902 Bill Morris 1234 Centre Lane NW St. Paul MN 55123 

Programa (galbūt, nors nebūtinai, servletas) išlaiko adresų knyga atmintyje kaip DOM Dokumentas objektas. Kai vartotojas pakeičia adresą, programos frontendas siunčia jam tik atnaujintą elementas.

elementas naudojamas unikaliai identifikuoti adresą; jis naudojamas kaip pagrindinis raktas. Tai neturėtų daug prasmės tikram pritaikymui, tačiau mes tai darome čia, kad viskas būtų paprasta.

Dabar turime parašyti „Java“ kodą, kuris padės mums identifikuoti šaltinio medžio elementas, kurį reikia pakeisti atnaujintu elementu. „findAddress“ () žemiau pateiktas metodas parodo, kaip tai galima pasiekti. Atminkite, kad, kad pavyzdys būtų trumpas, mes praleidome tinkamą klaidų tvarkymą.

public Node findAddress (eilutės pavadinimas, dokumento šaltinis) {Element root = source.getDocumentElement (); NodeList nl = root.getChildNodes (); // kartokite visus adresų mazgus ir raskite tą, kurio adresatas yra teisingas (int i = 0; i

Aukščiau pateiktą kodą greičiausiai būtų galima optimizuoti, tačiau akivaizdu, kad kartojimas per DOM medį gali būti varginantis ir linkęs į klaidas. Dabar pažvelkime, kaip galima rasti tikslinį mazgą, naudojant paprastą XPath sakinį. Pareiškimas gali atrodyti taip:

// adresas [vaikas :: adresatas [tekstas () = 'Jimas Smithas]]] 

Dabar galime perrašyti savo ankstesnį metodą. Šį kartą norimam mazgui rasti naudojame XPath sakinį:

public Node findAddress (eilutės pavadinimas, dokumento šaltinis) išmeta išimtį {// reikia atkurti kelis pagalbinius objektus XMLParserLiaison xpathSupport = new XMLParserLiaisonDefault (); XPathProcessor xpathParser = naujas XPathProcessorImpl (xpathSupport); PrefixResolver prefixResolver = new PrefixResolverDefault (source.getDocumentElement ()); // sukurk XPath ir inicializuok XPath xp = new XPath (); String xpString = "// adresas [vaikas :: adresatas [tekstas () = '" + vardas + "']]"; xpathParser.initXPath (xp, xpString, prefixResolver); // dabar vykdykite XPath select sakinį XObject list = xp.execute (xpathSupport, source.getDocumentElement (), prefixResolver); // grąžinti gautą mazgą return list.nodeset (). item (0); } 

Aukščiau pateiktas kodas gali atrodyti ne daug geriau nei ankstesnis bandymas, tačiau didžiąją dalį šio metodo turinio galima įtraukti į pagalbininkų klasę. Vienintelė dalis, kuri keičiasi vėl ir vėl, yra tikroji XPath išraiška ir tikslinis mazgas.

Tai leidžia mums sukurti „XPathHelper“ klasė, kuri atrodo taip:

importuoti org.w3c.dom. *; importuoti org.xml.sax. *; importuoti org.apache.xalan.xpath. *; importuoti org.apache.xalan.xpath.xml. *; public class XPathHelper {XMLParserLiaison xpathSupport = null; XPathProcessor xpathParser = null; PrefixResolver prefixResolver = null; XPathHelper () {xpathSupport = new XMLParserLiaisonDefault (); xpathParser = naujas XPathProcessorImpl (xpathSupport); } public NodeList processXPath (String xpath, Node target) thrws SAXException {prefixResolver = new PrefixResolverDefault (target); // sukurk XPath ir inicializuok XPath xp = new XPath (); xpathParser.initXPath (xp, xpath, prefixResolver); // dabar vykdykite XPath select sakinį XObject list = xp.execute (xpathSupport, target, prefixResolver); // grąžinti gautą mazgų grąžinimo sąrašą.nodeset (); }} 

Sukūrę pagalbininkų klasę, mes galime dar kartą perrašyti savo ieškiklio metodą, kuris dabar yra labai trumpas:

public Node findAddress (eilutės pavadinimas, dokumento šaltinis) išmeta išimtį {XPathHelper xpathHelper = new XPathHelper (); „NodeList“ nl = xpathHelper.processXPath ("// adresas [vaikas :: adresatas [tekstas () = '" + vardas + "']]], šaltinis.getDocumentElement ()); grąžinti nl.item (0); } 

Pagalbininkų klasė dabar gali būti naudojama, kai tam tikrame XML dokumente turi būti mazgas ar mazgų rinkinys. Tikrasis „XPath“ sakinys gali būti įkeltas net iš išorinio šaltinio, kad keičiant šaltinio dokumento struktūrą, pakeitimus būtų galima atlikti iš karto. Šiuo atveju kompiliavimo nereikia.

Apdorokite XML dokumentus naudodami XSL stiliaus lenteles

Kai kuriais atvejais yra tikslinga perduoti visą XML dokumento tvarkymą išoriniam XSL stiliaus lapui, šis procesas tam tikrais atžvilgiais yra panašus į XPath naudojimą, kaip aprašyta ankstesniame skyriuje. Naudodami „XSL“ stiliaus lapus, galite sukurti išvesties dokumentą, pasirinkdami mazgus iš įvesties dokumento ir sujungdami jų turinį su stiliaus lapo turiniu, remdamiesi šablono taisyklėmis.

Jei programa pakeičia XML dokumento struktūrą ir turinį ir sukuria naują dokumentą, gali būti geriau ir paprasčiau naudoti stiliaus stilių, o ne rašyti „Java“ programą, atliekančią tą patį darbą. Stilių lentelė greičiausiai yra saugoma išoriniame faile, leidžianti jį keisti betarpiškai, nereikia kompiliuoti.

Pvz., Galėtume užbaigti adresų knyga pavyzdį sukuriant stiliaus lapą, sujungiantį talpykloje saugomą adresų knyga su atnaujintu, taip sukurdamas naują dokumentą su jame esančiais atnaujinimais.

Štai tokio stiliaus lapo pavyzdys:

   //mymachine.com/changed.xml