Programmering

XSLT blomstrer med Java

Har du noen gang blitt stumpet av et vanskelig XML-transformasjonsproblem som du ikke kunne løse med XSLT (Extensible Stylesheet Language Transformation) alene? Ta for eksempel et enkelt filterstilark som bare velger de noder datert tidligere enn for fem dager siden. Du har hørt at XSLT kan filtrere XML-dokumenter, så du finner ut at du vil løse dette problemet på kort tid. Den første oppgaven er å hente dagens dato fra et stilark, forutsatt at informasjon ikke er inkludert i det originale XML-dokumentet. Dessverre kan du ikke fullføre denne oppgaven med bare XSLT. I en situasjon som denne kan du forenkle XSLT-koden og løse problemet raskere med en Java-utvidelse.

Mange XSLT-prosessorer tillater noen form for utvidelsesmekanisme; spesifikasjonen krever at de gjør det. I verden av Java og XML er den mest brukte XSLT-prosessoren åpen kildekode Apache Xalan-prosessor. Xalan er skrevet på Java og tillater utvidelser i Java. Mange utviklere synes Xalans utvidbarhet er kraftig fordi den lar dem bruke Java-ferdighetene sine fra stilarkkonteksten. Tenk på måten JSPer (JavaServer Pages), skriptlets og egendefinerte koder gir HTML kraft. Xalan-utvidelser gir makt til stilark på omtrent samme måte: ved å gi Java-utviklere tilgang til deres favorittverktøy, Java.

I denne artikkelen vil jeg demonstrere hvordan du kan bruke Java fra et XSLT-stilark. Først vil vi bruke Xalans utvidbarhet til å sette i gang og bruke eksisterende klasser innen JDK. Senere vil jeg vise deg hvordan du skriver en XSLT-utvidelsesfunksjon som tar en String argumentet og returnerer et DOM (Document Object Model) fragment til stilarkprosessoren.

XSLT er viktig for J2EE (Java 2 Platform, Enterprise Edition) -utviklere fordi styling av XML-dokumenter har blitt en server-operasjon. Også JAXP (Java API for XML Processing), som inkluderer støtte for XSLT-motorer, har blitt en del av J2EE-spesifikasjonen (J2EE 2.6.11). I begynnelsen var XSLT ment å style XML på klienten; Imidlertid styler de fleste applikasjoner XML før de sendes til klienten. For J2EE-utviklere betyr dette at XSLT-prosessoren mest sannsynlig vil kjøre på app-serveren.

Før du fortsetter med denne artikkelen, vær advart om at bruk av Java-utvidelser i XSLT-stilark vil redusere bærbarheten. Mens utvidelser er en del av XSLT-spesifikasjonen, er ikke måten de implementeres på. Hvis stilarkene dine kjøres på andre prosessorer enn Xalan, for eksempel stilmotoren til Internet Explorer, bør du unngå å bruke utvidelser for enhver pris.

XSLT svakheter

Fordi XSLT har noen svake punkter, viser XSLT-utvidelser seg ganske nyttige. Jeg sier ikke at XSLT er dårlig; det tilbyr imidlertid ikke det beste verktøyet for å behandle alt i et XML-dokument. Vurder denne delen av XML:

 XSLT er ikke så lett å bruke som noen vil ha deg ... 

Anta at sjefen din ber deg om å endre et stilark slik at det konverterer alle forekomster av "er ikke" til "er ikke" og lokaliserer vanlige etiketter. Sikkert gir XSLT en mekanisme for å gjøre noe i denne retning, ikke sant? Feil. XSLT gir ingen enkel måte å erstatte forekomsten av et ord eller mønster i en streng. Det samme gjelder lokalisering. Det er ikke å si at det ikke kan gjøres med standard XSLT-syntaks. Det er måter, men de er ikke så enkle som vi ønsker. Hvis du virkelig vil skrive tekstmanipuleringsfunksjoner ved hjelp av rekursive maler, vær min gjest.

XSLTs viktigste svakhet er tekstbehandling, noe som virker rimelig siden formålet er å gjengi XML. Men fordi XML-innhold er helt tekst, trenger XSLT sterkere tekstbehandling. Det er unødvendig å si at stilarkdesignere krever en viss utvidelse fra tid til annen. Med Xalan gir Java denne utvidbarheten.

Bruk JDK-klasser innen XSLT

Du kan være glad for å vite at du ikke trenger å skrive noen Java-kode for å dra nytte av Xalans utvidbarhet. Når du bruker Xalan, kan du opprette og påkalle metoder på nesten alle Java-objekter. Før du bruker en Java-klasse, må du oppgi en XSLT navneområdet for det. Dette eksemplet erklærer "java" som et navneområde for alt i eller under Java-pakken (dvs. hele JDK):

Nå trenger vi noe å gjøre. La oss starte med et lite XML-dokument:

 Java kan være en kjepphest J. Burke 30.11.97 

Du er blitt bedt om å utforme denne XML-en slik at tittelen vises med store bokstaver. En utvikler som er ny i XSLT, vil ganske enkelt åpne en XSLT-referanse for å se etter toUpper () funksjon; hun ville imidlertid være skuffet over å finne at referansen mangler en. De oversette() metoden er det beste alternativet, men jeg har en enda bedre metode: java.lang.String.toUpperCase (). For å bruke denne metoden, må du starte en String objekt med tittelinnholdet. Slik kan du lage en ny String forekomst med tittelelementets innhold:

De Navn attributt spesifiserer håndtaket til det nye String forekomst. Du påkaller konstruktøren ved først å spesifisere navneområdet sammen med den gjenværende banen til String klasse. Som du kanskje har lagt merke til, String mangler a ny() metode. Du bruker ny() å konstruere et Java-objekt i Xalan; det tilsvarer Java ny nøkkelord. Argumentene gitt til ny() bestemme konstruktørversjonen som skal kalles. Nå som du har tittelinnholdet i en Java String objekt, kan du bruke toUpperCase () metode, slik:

Dette kan se rart ut for deg først. Når du bruker Java-metoder på en bestemt forekomst, er det første argumentet den forekomsten du vil at metoden skal påberopes på. Åpenbart bruker Xalan introspeksjon for å gi denne muligheten.

Nedenfor finner du et annet triks. Slik kan du sende ut dato og klokkeslett hvor som helst i stilarket ditt ved hjelp av java.lang. dato:

Her er noe som vil gjøre dagen til alle som trenger å lokalisere et generelt stilark mellom to eller flere språk. Du kan bruke java.util.ResourceBundle for å lokalisere bokstavelig tekst i et stilark. Siden XML har en forfatterkode, vil du kanskje skrive ut "Forfatter:" ved siden av personens navn.

Et alternativ er å lage et eget stilark for hvert sted, dvs. en for engelsk, et annet for kinesisk og så videre. Problemene som ligger i denne tilnærmingen bør være tydelige. Å holde flere versjoner av stilark er konsistente er tidkrevende. Du må også endre applikasjonen slik at den velger riktig stilark basert på brukerens lokalitet.

I stedet for å duplisere stilarket for hvert språk, kan du dra nytte av Java's lokaliseringsfunksjoner. Lokalisering ved hjelp av en ResourceBundle viser en bedre tilnærming. Innen XSLT, last inn ResourceBundle i begynnelsen av stilarkene dine, slik:

De ResourceBundle klasse forventer å finne en fil som heter Generelle eiendommer i din CLASSPATH. Når pakken er opprettet, kan den brukes på nytt gjennom stilarket. Dette eksemplet henter forfatter ressurs:

Legg merke til den merkelige metodesignaturen igjen. Normalt, ResourceBundle.getString () tar bare ett argument; Imidlertid må du i XSLT også spesifisere objektet som du vil påkalle metoden.

Skriv dine egne utvidelser

I noen sjeldne situasjoner kan det hende du må skrive din egen XSLT-utvidelse, i form av enten en utvidelsesfunksjon eller et utvidelseselement. Jeg vil diskutere å lage en utvidelsesfunksjon, et konsept som er ganske lett å forstå. Enhver Xalan-utvidelsesfunksjon kan ta strenger som inngangs- og returstrenger til XSLT-prosessoren. Utvidelsene dine kan også ta NodeLists eller Nodes som argumenter og returner disse typene til XSLT-prosessoren. Ved hjelp av Nodes eller NodeLists betyr at du kan legge til det originale XML-dokumentet med en utvidelsesfunksjon, og det er det vi vil gjøre.

En type tekstelement som du ofte møter, er en dato; det gir en flott mulighet for en ny XSLT-utvidelse. Vår oppgave er å style et artikkelelement slik at datoen skrives ut i følgende format:

Fredag, 30. november 200

Kan standard XSLT fullføre datoen ovenfor? XSLT kan fullføre det meste av oppgaven. Å bestemme den faktiske dagen er den vanskelige delen. En måte å raskt løse dette problemet er å bruke java.text.SimpleDate formatklasse i en utvidelsesfunksjon for å returnere en streng formatert som vi ønsker. Men vent: legg merke til at dagen vises i fet skrift. Dette returnerer oss til det opprinnelige problemet. Grunnen til at vi til og med vurderer en utvidelsesfunksjon er fordi det opprinnelige XML-dokumentet ikke klarte å strukturere datoen som en gruppe noder. Hvis utvidelsesfunksjonen vår returnerer en streng, vil vi fortsatt synes det er vanskelig å style dagsfeltet annerledes enn resten av datostrengen. Her er et mer nyttig format, i det minste sett fra perspektivet til en XSLT-designer:

  11 30 2001  

Vi oppretter nå en XSLT-utvidelsesfunksjon, tar en streng som argument og returnerer en XML-node i dette formatet:

  30. november fredag ​​2001 

Klassen som er vert for utvidelsesfunksjonen vår implementerer eller utvider ikke noe; vi vil ringe klassen DateFormatter:

offentlig klasse DateFormatter {offentlig statisk nodeformat (strengdato) {} 

Wow, for lett, ikke sant? Det er absolutt ingen krav til typen eller grensesnittet til en Xalan-utvidelsesfunksjon. Vanligvis vil de fleste utvidelsesfunksjoner ta en String som et argument og returnere en annen String. Andre vanlige mønstre er å sende eller motta org.w3c.dom.NodeLists eller individ Nodes fra en utvidelsesfunksjon, som vi vil gjøre. Se Xalan-dokumentasjonen for detaljer om hvordan Java-typer konverterer til XSLT-typer.

I kodefragmentet ovenfor er format() metodens logikk brytes i to deler. Først må vi analysere datastrengen fra det originale XML-dokumentet. Deretter bruker vi noen DOM-programmeringsteknikker for å lage en Node og returner den til XSLT-prosessoren. Kroppen til vår format() metodeimplementering lyder:

 Document doc = DocumentBuilderFactory.newInstance (). newDocumentBuilder (). newDocument (); Element dateNode = doc.createElement ("formatert dato"); SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance (DateFormat.SHORT, locale); df.setLenient (true); Dato d = df. Parse (dato); df.applyPattern ("MMMM"); addChild (dateNode, "måned", df.format (d)); df.applyPattern ("EEEE"); addChild (dateNode, "ukedag", df.format (d)); df.applyPattern ("åååå"); dateNode.setAttribute ("år", df.format (d)); retur datoNode; 

dateNode inneholder våre formaterte datoverdier som vi returnerer til stilarket. Legg merke til at vi har brukt java.text.SimpleDateFormat () for å analysere datoen. Dette lar oss dra full nytte av Javas datostøtte, inkludert lokaliseringsfunksjonene. SimpleDateFormat håndterer den numeriske datakonvertering og returnerer måned og dag navn som samsvarer med lokaliteten til den virtuelle maskinen som kjører applikasjonen vår.

Husk: det primære formålet med en utvidelsesfunksjon er ganske enkelt å gi oss tilgang til eksisterende Java-funksjonalitet; skriv så lite kode som mulig. En utvidelsesfunksjon, som enhver Java-metode, kan bruke andre metoder innen samme klasse. For å forenkle format() implementering, flyttet jeg repeterende kode til en liten verktøymetode:

private void addChild (Node foreldre, strengnavn, strengtekst) {Element child = parent.getOwnerDocument (). createElement (name); child.appendChild (parent.getOwnerDocument (). createTextNode (tekst)); foreldre.appendChild (barn); } 

Bruk DateFormatter i et stilark

Nå som vi har implementert en utvidelsesfunksjon, kan vi kalle den fra et stilark. Akkurat som før, må vi erklære et navneområde for utvidelsesfunksjonen vår:

Denne gangen kvalifiserte vi helt veien til klassen som er vert for utvidelsesfunksjonen. Dette er valgfritt og avhenger av om du bruker andre klasser i samme pakke eller bare et enkelt utvidelsesobjekt. Du kan erklære det fulle CLASSPATH som navneområdet eller bruk en pakke og spesifiser klassen der utvidelsesfunksjonen påkalles. Ved å spesifisere det fulle CLASSPATH, vi skriver mindre når vi kaller funksjonen.

For å bruke funksjonen, kan du bare kalle den fra a å velge tag, slik som:



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