Programavimas

XSLT žydi su „Java“

Ar kada nors jus apėmė sunki XML transformacijos problema, kurios negalėjote išspręsti vien naudodamiesi XSLT (Extensible Stylesheet Language Transformation)? Paimkime, pavyzdžiui, paprastą filtro stiliaus lapą, kuris parenka tik tuos mazgų, datuotų anksčiau nei prieš penkias dienas. Girdėjote, kad XSLT gali filtruoti XML dokumentus, todėl manote, kad greitai išspręsite šią problemą. Pirmoji užduotis yra gauti šios dienos datą iš stiliaus lapo, jei informacija nėra įtraukta į pradinį XML dokumentą. Deja, jūs negalite atlikti šios užduoties naudodami tik XSLT. Tokioje situacijoje galite supaprastinti savo XSLT kodą ir greičiau išspręsti problemą naudodami „Java“ plėtinį.

Daugelis XSLT procesorių leidžia naudoti tam tikro tipo išplėtimo mechanizmus; specifikacija reikalauja, kad jie tai padarytų. Java ir XML pasaulyje plačiausiai naudojamas XSLT procesorius yra atvirojo kodo Apache Xalan procesorius. Parašytas „Java“, „Xalan“ leidžia „Java“ plėtinius. Daugeliui kūrėjų atrodo, kad „Xalan“ išplečiamumas yra galingas, nes tai leidžia jiems panaudoti savo „Java“ įgūdžius stiliaus lapo kontekste. Apsvarstykite, kaip JSP („JavaServer Pages“), scenarijai ir tinkintos žymos suteikia galią HTML. „Xalan“ plėtiniai suteikia stiliaus lapų galios panašiai: suteikdami „Java“ kūrėjams prieigą prie savo mėgstamiausio įrankio „Java“.

Šiame straipsnyje aš pademonstruosiu, kaip galite naudoti „Java“ iš XSLT stiliaus lapo. Pirma, naudosime „Xalan“ išplėtimą, norėdami sukurti ir panaudoti esamas klases JDK. Vėliau aš jums parodysiu, kaip parašyti XSLT plėtinio funkciją, kuri užima a Stygos argumentą ir grąžina DOM (Document Object Model) fragmentą į stiliaus lapo procesorių.

XSLT yra svarbus J2EE („Java 2 Platform“, „Enterprise Edition“) kūrėjams, nes XML dokumentų stilius tapo serverio operacija. Taip pat JAXP („Java“ API, skirtas XML apdorojimui), kuris apima „XSLT“ variklių palaikymą, tapo „J2EE“ specifikacijos dalimi („J2EE 2.6.11“). Dar kūdikystėje XSLT buvo skirtas XML formavimui klientui; tačiau dauguma programų XML formatuoja prieš siunčiant ją klientui. J2EE kūrėjams tai reiškia, kad XSLT procesorius greičiausiai veiks programų serveryje.

Prieš tęsdami šį straipsnį, įspėkite, kad naudojant „Java“ plėtinius XSLT stiliaus lapuose sumažės jų perkeliamumas. Nors plėtiniai yra XSLT specifikacijos dalis, jų diegimo būdas nėra. Jei jūsų stiliaus lapai bus vykdomi ne Xalan, o kituose procesoriuose, pvz., „Internet Explorer“ stiliaus lapų variklyje, turėtumėte bet kokia kaina nenaudoti plėtinių.

XSLT silpnybės

Kadangi XSLT turi silpnų vietų, XSLT plėtiniai yra gana naudingi. Nesakau, kad XSLT yra blogas; tačiau jis tiesiog nesiūlo geriausio įrankio viskam apdoroti XML dokumente. Apsvarstykite šį XML skyrių:

 XSLT naudoti nėra taip paprasta, kaip kai kurie ... 

Tarkime, kad jūsų viršininkas paprašys modifikuoti stiliaus lapą, kad jis visus „ne“ atvejus paverstų „ne“ ir lokalizuotų bendras etiketes. Be abejo, XSLT pateikia mechanizmą, kaip kažką daryti pagal šias linijas, tiesa? Neteisingai. XSLT nėra paprastas būdas pakeisti žodžio ar rašto atsiradimą eilutėje. Tas pats pasakytina ir apie lokalizaciją. Tai nereiškia, kad to negalima padaryti naudojant standartinę XSLT sintaksę. Yra būdų, tačiau jie nėra toli gražu ne tokie lengvi, kaip norėtume. Jei tikrai norite rašyti manipuliavimo tekstu funkcijas naudodami rekursinius šablonus, būkite mano svečias.

Pagrindinis XSLT trūkumas yra teksto apdorojimas, kuris atrodo pagrįstas, nes jo tikslas yra pateikti XML. Tačiau, kadangi XML turinys yra tik tekstas, XSLT reikia griežtesnio teksto tvarkymo. Nereikia nė sakyti, kad stiliaus lapų dizaineriai reikalauja tam tikro išplėtimo. Su „Xalan“ „Java“ suteikia šį išplėtimą.

Naudokite JDK klases XSLT

Jums gali būti malonu žinoti, kad norint pasinaudoti „Xalan“ išplėtimo galimybėmis nereikia rašyti jokio „Java“ kodo. Kai naudojate „Xalan“, galite sukurti ir naudoti metodus beveik bet kuriame „Java“ objekte. Prieš naudodami „Java“ klasę, turite pateikti XSLT vardų sritis už jį. Šis pavyzdys skelbia „java“ kaip visko, esančio „Java“ pakete arba po juo (t. y. viso JDK), vardų sritis:

Dabar mums reikia ką nors padaryti. Pradėkime nuo mažo XML dokumento:

 Java gali būti mada J. Burke 97/11/30 

Jūsų buvo paprašyta sukurti šį XML, kad pavadinimas būtų rodomas didžiosiomis raidėmis. Naujas XSLT kūrėjas paprasčiausiai atidaro XSLT nuorodą ieškoti viršuje () funkcija; tačiau ji nusivylė sužinojusi, kad nuorodoje jos nėra. versti () metodas yra geriausias pasirinkimas, bet turiu dar geresnį metodą: java.lang.String.toUpperCase (). Norėdami naudoti šį metodą, turite iš karto suaktyvinti a Stygos objektas su pavadinimo turiniu. Štai kaip galite sukurti naują Stygos egzempliorius su pavadinimo elemento turiniu:

vardas atributas nurodo jūsų naujosios rankeną Stygos instancija. Jūs sukviečiate konstruktorių pirmiausia nurodydami vardų sritį kartu su likusiu keliu į Stygos klasė. Kaip jau pastebėjote, Stygos trūksta a naujas () metodas. Tu naudoji naujas () sukonstruoti „Java“ objektą „Xalan“; jis atitinka „Java“ naujas raktinis žodis. Pateikti argumentai naujas () nustatyti konstruktoriaus versiją, kuri bus pašauktas. Dabar, kai turite pavadinimo turinį „Java“ Stygos objektą, galite naudoti toUpperCase () metodas, panašiai kaip:

Iš pradžių tai gali pasirodyti keista. Kai naudojate „Java“ metodus konkrečiame egzemplioriuje, pirmasis argumentas yra tas egzempliorius, į kurį norite nukreipti metodą. Akivaizdu, kad Xalanas naudojasi savistaba, kad suteiktų šią galimybę.

Žemiau rasite dar vieną gudrybę. Štai kaip jūs galite išskleisti datą ir laiką bet kurioje savo stiliaus lapo vietoje naudodami java.lang.Data:

Štai kas privers visus, kuriems reikia lokalizuoti bendrąjį stiliaus lapą tarp dviejų ar daugiau kalbų. Tu gali naudoti java.util.ResourceBundle norint lokalizuoti pažodinį tekstą stiliaus lape. Kadangi jūsų XML turi autoriaus žymą, galbūt norėsite atsispausdinti "Autorius:" šalia asmens vardo.

Viena iš galimybių yra sukurti atskirą stilių lapą kiekvienai lokalei, t. Y. Vieną anglų kalbai, kitą kinų kalbai ir pan. Šiam požiūriui būdingos problemos turėtų būti akivaizdžios. Laikyti kelias stiliaus lapo versijas nuosekliai užima daug laiko. Taip pat turite modifikuoti savo programą taip, kad ji pasirinktų teisingą stiliaus lapą pagal vartotojo lokalę.

Užuot dubliavę kiekvienos kalbos stilių, galite pasinaudoti „Java“ lokalizavimo funkcijomis. Lokalizavimas naudojant a „ResourceBundle“ įrodo geresnį požiūrį. Į XSLT įkelkite „ResourceBundle“ savo stiliaus lentelių pradžioje, pavyzdžiui:

„ResourceBundle“ klasė tikisi rasti failą pavadinimu Bendrosios savybės jūsų CLASSPATH. Sukūrus paketą, jį galima pakartotinai naudoti visame stiliaus lape. Šis pavyzdys pateikia autorius šaltinis:

Dar kartą atkreipkite dėmesį į keistą metodo parašą. Paprastai ResourceBundle.getString () imasi tik vieno argumento; tačiau XSLT taip pat turite nurodyti objektą, kuriuo norite pasinaudoti metodu.

Parašykite savo plėtinius

Kai kuriais retais atvejais gali tekti parašyti savo XSLT plėtinį kaip plėtinio funkciją arba plėtinio elementą. Aptarsiu išplėtimo funkcijos sukūrimą - gana lengvai suvokiamą koncepciją. Bet kuri „Xalan“ plėtinio funkcija gali priimti eilutes kaip įvestį ir grąžinti eilutes į XSLT procesorių. Taip pat gali prireikti jūsų plėtinių „NodeList“s arba Mazgass kaip argumentus ir grąžinkite šiuos tipus į XSLT procesorių. Naudojant Mazgass arba „NodeList“s reiškia, kad galite pridėti originalų XML dokumentą su plėtinio funkcija, ką mes ir padarysime.

Vieno tipo teksto elementas, su kuriuo dažnai susiduriama, yra data; tai suteikia puikią galimybę naujam XSLT plėtiniui. Mūsų užduotis yra stiliaus straipsnio elementas, kad data būtų išspausdinta tokiu formatu:

Penktadienis, 200 lapkričio 30 d

Ar standartinė XSLT gali užpildyti anksčiau nurodytą datą? XSLT gali atlikti didžiąją dalį užduoties. Tikrą dieną nustatyti yra sudėtinga. Vienas iš būdų greitai išspręsti šią problemą yra naudoti java.text.SimpleDate formato klasę pratęsimo funkcijoje, kad grąžintų eilutę, suformatuotą taip, kaip norime. Bet palaukite: atkreipkite dėmesį, kad diena rodoma paryškintu tekstu. Tai grąžina mus į pradinę problemą. Priežastis, dėl kurios mes netgi svarstome plėtinio funkciją, yra ta, kad pradiniame XML dokumente nepavyko struktūrizuoti datos kaip mazgų grupės. Jei mūsų plėtinio funkcija grąžins eilutę, mes tai padarysime vis tiek sunku suformuoti dienos lauką kitaip nei likusi datos eilutė. Čia yra naudingesnis formatas, bent jau iš XSLT dizainerio perspektyvos:

  11 30 2001  

Dabar mes sukuriame XSLT plėtinio funkciją, kaip argumentą imdami eilutę ir pateikdami XML mazgą tokiu formatu:

  2001 m. Lapkričio 30 d., Penktadienis 

Mūsų pratęsimo funkciją talpinanti klasė nieko neįgyvendina ir neplatina; paskambinsime klasei DataFormatter:

public class DateFormatter {public static Node format (String date) {} 

Oho, per lengva, ar ne? „Xalan“ pratęsimo funkcijos tipui ar sąsajai nėra keliami jokie reikalavimai. Paprastai daugumai išplėtimo funkcijų prireiks a Stygos kaip argumentą ir grąžinti kitą Stygos. Kiti įprasti būdai yra siųsti ar gauti org.w3c.dom.NodeLists ar individualus Mazgass iš pratęsimo funkcijos, kaip mes darysime. Norėdami sužinoti daugiau, kaip „Java“ tipai konvertuojami į XSLT tipus, žr. „Xalan“ dokumentaciją.

Viršuje esančiame kodo fragmente formatas () metodo logika skyla į dvi dalis. Pirmiausia turime išanalizuoti datos eilutę iš pradinio XML dokumento. Tada mes naudojame keletą DOM programavimo metodų, kad sukurtume Mazgas ir grąžinkite jį į XSLT procesorių. Mūsų kūnas formatas () metodo įgyvendinimas yra toks:

 Document doc = DocumentBuilderFactory.newInstance (). newDocumentBuilder (). newDocument (); Elementas dateNode = doc.createElement ("suformatuota data"); SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance (DateFormat.SHORT, lokalė); df.setLenient (true); Data d = df.parse (data); df.applyPattern ("MMMM"); addChild (dateNode, "mėnuo", df.formatas (d)); df.applyPattern („EEEE“); addChild (dateNode, "savaitės diena", df.format (d)); df.applyPattern ("yyyy"); dateNode.setAttribute ("metai", df.formatas (d)); grąžinimo dataNode; 

dateNode bus mūsų suformatuotos datos reikšmės, kurias grįšime į stiliaus lapą. Atkreipkite dėmesį, kad mes pasinaudojome java.text.SimpleDateFormat () išanalizuoti datą. Tai leidžia mums visapusiškai pasinaudoti „Java“ datos palaikymu, įskaitant lokalizavimo funkcijas. „SimpleDateFormat“ tvarko skaitinę datos konvertavimą ir pateikia mėnesių ir dienų pavadinimus, atitinkančius VM, kuriame veikia mūsų programa, lokalę.

Atminkite: pagrindinis išplėtimo funkcijos tikslas yra tiesiog leisti mums pasiekti esamas „Java“ funkcijas; parašykite kuo mažiau kodo. Plėtinio funkcija, kaip ir bet kuris „Java“ metodas, gali naudoti kitus tos pačios klasės metodus. Supaprastinti formatas () įgyvendindamas perkėliau pasikartojantį kodą į nedidelį naudingumo metodą:

private void addChild (Mazgo tėvas, eilutės pavadinimas, eilutės tekstas) {Elementas vaikas = tėvas.getOwnerDocument (). createElement (vardas); child.appendChild (parent.getOwnerDocument (). createTextNode (tekstas)); parent.appendChild (vaikas); } 

Stiliaus lape naudokite „DateFormatter“

Dabar, kai įdiegėme plėtinio funkciją, galime ją iškviesti iš stiliaus lapo. Kaip ir anksčiau, turime deklaruoti išplėtimo funkcijos vardų sritį:

Šį kartą mes visiškai kvalifikavome kelią į klasę, kurioje yra plėtinio funkcija. Tai neprivaloma ir priklauso nuo to, ar naudosite kitas klases tame pačiame pakete, ar tik vieną plėtinio objektą. Galite paskelbti pilną CLASSPATH kaip vardų sritį arba naudokite paketą ir nurodykite klasę, kurioje naudojama plėtinio funkcija. Nurodant pilną CLASSPATH, mes įvedame mažiau, kai iškviečiame funkciją.

Norėdami pasinaudoti funkcija, paprasčiausiai paskambinkite iš „a“ pasirinkite žyma, tokia: