Programmering

XML-dokumentbehandling i Java ved bruk av XPath og XSLT

Extensible Markup Language (XML) er absolutt en av de hotteste teknologiene for øyeblikket. Selv om begrepet markeringsspråk ikke er nytt, virker XML spesielt attraktivt for Java- og Internett-programmerere. Java API for XML-parsing (JAXP; se Ressurser), som nylig er definert gjennom Java Community-prosessen, lover å gi et felles grensesnitt for tilgang til XML-dokumenter. W3C har definert den såkalte Document Object Model (DOM), som gir et standardgrensesnitt for å jobbe med et XML-dokument i et trehierarki, mens Simple API for XML (SAX) lar et program analysere et XML-dokument sekvensielt, basert på en hendelseshåndteringsmodell. Begge disse standardene (SAX er en de facto-standard) utfyller JAXP. Sammen gir disse tre API-ene tilstrekkelig støtte for å håndtere XML-dokumenter i Java, og mange bøker på markedet beskriver bruken av dem.

Denne artikkelen introduserer en måte å håndtere XML-dokumenter som går utover standard Java APIer for å manipulere XML. Vi ser at i mange tilfeller gir XPath og XSLT enklere og mer elegante måter å løse applikasjonsproblemer på. I noen enkle eksempler vil vi sammenligne en ren Java / XML-løsning med en som bruker XPath og / eller XSLT.

Både XSLT og XPath er en del av Extensible Stylesheet Language (XSL) spesifikasjonen (se Ressurser). XSL består av tre deler: XSL-språkspesifikasjonen, XSL-transformasjoner (XSLT) og XML Path Language (XPath). XSL er et språk for transformasjon av XML-dokumenter; den inneholder en definisjon - Formatering av objekter - av hvordan XML-dokumenter kan formateres for presentasjon. XSLT spesifiserer et ordforråd for å transformere ett XML-dokument til et annet. Du kan betrakte XSLT som XSL minus formateringsobjekter. XPath-språket adresserer spesifikke deler av XML-dokumenter og er ment å brukes fra et XSLT-stilark.

I forbindelse med denne artikkelen antas det at du er kjent med det grunnleggende om XML og XSLT, samt DOM API-er. (For informasjon og veiledning om disse emnene, se Ressurser.)

Merk: Denne artikkelens kodeeksempler ble samlet og testet med Apache Xerces XML-parser og Apache Xalan XSL-prosessor (se Ressurser).

Problemet

Mange artikler og artikler som omhandler XML, sier at det er det perfekte verktøyet for å oppnå god designpraksis i webprogrammering: Model-View-Controller-mønsteret (MVC), eller, i enklere termer, separasjonen av applikasjonsdata fra presentasjonsdata . Hvis applikasjonsdataene er formatert i XML, kan de lett bindes - vanligvis i en servlet eller Java ServerPage - til for eksempel HTML-maler ved å bruke et XSL-stilark.

Men XML kan gjøre mye mer enn bare å hjelpe med separasjon av modellvisning for applikasjonens frontend. Vi ser for tiden mer og mer utbredt bruk av komponenter (for eksempel komponenter utviklet ved bruk av EJB-standarden) som kan brukes til å montere applikasjoner, og dermed forbedre utviklerens produktivitet. Gjenbrukbarhet av komponenter kan forbedres ved å formatere dataene som komponentene håndterer på en standard måte. Vi kan faktisk forvente å se flere og flere publiserte komponenter som bruker XML for å beskrive deres grensesnitt.

Fordi XML-formatert data er språknøytral, blir den brukbar i tilfeller der klienten til en gitt applikasjonstjeneste ikke er kjent, eller når den ikke må ha noen avhengighet av serveren. I B2B-miljøer kan det for eksempel ikke være akseptabelt for to parter å ha avhengighet av konkrete Java-objektgrensesnitt for deres datautveksling. Nye teknologier som Simple Object Access Protocol (SOAP) (se Resources) imøtekommer disse kravene.

Alle disse sakene har en ting til felles: data lagres i XML-dokumenter og må manipuleres av et program. For eksempel vil et program som bruker forskjellige komponenter fra forskjellige leverandører, mest sannsynlig måtte endre strukturen på (XML) dataene slik at det passer til applikasjonens behov eller følge en gitt standard.

Kode skrevet med Java API-ene som er nevnt ovenfor, vil absolutt gjøre dette. Videre er det flere og flere verktøy tilgjengelig som du kan gjøre et XML-dokument om til en JavaBean og omvendt, noe som gjør det lettere å håndtere dataene fra et Java-program. I mange tilfeller behandler applikasjonen, eller i det minste en del av den, bare ett eller flere XML-dokumenter som input og konverterer dem til et annet XML-format som output. Å bruke stilark i disse tilfellene er et levedyktig alternativ, som vi vil se senere i denne artikkelen.

Bruk XPath til å finne noder i et XML-dokument

Som nevnt ovenfor brukes XPath-språket til å finne bestemte deler av et XML-dokument. Som sådan er det ment å brukes av et XSLT-stilark, men ingenting hindrer oss i å bruke det i Java-programmet vårt for å unngå langvarig iterasjon over et DOM-elementhierarki. Faktisk kan vi la XSLT / XPath-prosessoren gjøre jobben for oss. La oss se på hvordan dette fungerer.

La oss anta at vi har et applikasjonsscenario der et XML-kildedokument blir presentert for brukeren (muligens etter å ha blitt behandlet av et stilark). Brukeren gjør oppdateringer til dataene, og for å lagre nettverksbåndbredde, sender bare de oppdaterte postene tilbake til applikasjonen. Programmet ser etter XML-fragmentet i kildedokumentet som må oppdateres, og erstatter det med de nye dataene.

Vi vil lage et lite utvalg som hjelper deg med å forstå de forskjellige alternativene. For dette eksemplet antar vi at applikasjonen omhandler adresseposter i en adressebok. En prøve adressebok dokumentet ser slik ut:

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

Søknaden (muligens, men ikke nødvendigvis, en servlet) holder en forekomst av adressebok i minnet som en DOM Dokument gjenstand. Når brukeren endrer en adresse, sender programmets frontend den bare den oppdaterte element.

De elementet brukes til å identifisere en adresse unikt; den fungerer som hovednøkkel. Dette ville ikke være veldig fornuftig for en reell applikasjon, men vi gjør det her for å holde ting enkelt.

Vi må nå skrive litt Java-kode som vil hjelpe oss med å identifisere element i kildetreet som må erstattes med det oppdaterte elementet. De findAddress () metoden nedenfor viser hvordan det kan oppnås. Vær oppmerksom på at for å holde prøven kort har vi utelatt riktig feilhåndtering.

offentlig Node findAddress (strengnavn, dokumentkilde) {Element root = source.getDocumentElement (); NodeList nl = root.getChildNodes (); // gjenta over alle adressenoder og finn den som har riktig adressat for (int i = 0; i

Koden ovenfor kan mest sannsynlig optimaliseres, men det er åpenbart at iterering over DOM-treet kan være kjedelig og feil utsatt. La oss nå se på hvordan målnoden kan lokaliseres ved hjelp av en enkel XPath-setning. Uttalelsen kan se slik ut:

// address [child :: addressee [text () = 'Jim Smith']] 

Vi kan nå omskrive vår forrige metode. Denne gangen bruker vi XPath-setningen for å finne ønsket node:

offentlig Node findAddress (strengnavn, dokumentkilde) kaster Unntak {// trenger å gjenskape noen få hjelpeobjekter XMLParserLiaison xpathSupport = ny XMLParserLiaisonDefault (); XPathProcessor xpathParser = ny XPathProcessorImpl (xpathSupport); PrefixResolver prefixResolver = nytt PrefixResolverDefault (source.getDocumentElement ()); // opprett XPath og initialiser den XPath xp = new XPath (); Streng xpString = "// adresse [underordnet :: adressat [tekst () = '" + navn + "']]"; xpathParser.initXPath (xp, xpString, prefixResolver); // utfør nå XPath select-setningen XObject list = xp.execute (xpathSupport, source.getDocumentElement (), prefixResolver); // returner den resulterende noderettelisten. nodesett (). element (0); } 

Ovennevnte kode ser kanskje ikke mye bedre ut enn forrige forsøk, men det meste av innholdet i denne metoden kan være innkapslet i en hjelperklasse. Den eneste delen som endres om og om igjen er det faktiske XPath-uttrykket og målnoden.

Dette lar oss lage en XPathHelper klasse, som ser slik ut:

importer org.w3c.dom. *; importer org.xml.sax. *; importer org.apache.xalan.xpath. *; importer org.apache.xalan.xpath.xml. *; offentlig klasse XPathHelper {XMLParserLiaison xpathSupport = null; XPathProcessor xpathParser = null; PrefixResolver prefixResolver = null; XPathHelper () {xpathSupport = ny XMLParserLiaisonDefault (); xpathParser = ny XPathProcessorImpl (xpathSupport); } offentlig NodeList-prosessXPath (String xpath, Node target) thrws SAXException {prefixResolver = new PrefixResolverDefault (target); // opprett XPath og initialiser den XPath xp = new XPath (); xpathParser.initXPath (xp, xpath, prefixResolver); // utfør nå XPath select-setningen XObject list = xp.execute (xpathSupport, target, prefixResolver); // returner den resulterende nodelisten. nodesett (); }} 

Etter å ha opprettet hjelperklassen, kan vi omskrive finnemetoden vår igjen, som nå er veldig kort:

offentlig Node findAddress (strengnavn, dokumentkilde) kaster unntak {XPathHelper xpathHelper = ny XPathHelper (); NodeList nl = xpathHelper.processXPath ("// address [child :: addressee [text () = '" + name + "']]", source.getDocumentElement ()); return nl.item (0); } 

Hjelperklassen kan nå brukes når en node eller et sett med noder må plasseres i et gitt XML-dokument. Den faktiske XPath-setningen kan til og med lastes fra en ekstern kilde, slik at endringer kan gjøres på farten hvis kildedokumentstrukturen endres. I dette tilfellet er ingen rekompilering nødvendig.

Behandle XML-dokumenter med XSL-stilark

I noen tilfeller er det fornuftig å outsource hele håndteringen av et XML-dokument til et eksternt XSL-stilark, en prosess som i noen henseender ligner bruken av XPath som beskrevet i forrige avsnitt. Med XSL-stilark kan du opprette et utdatadokument ved å velge noder fra inndokumentet og slå sammen innholdet med stilarkinnhold, basert på mønsterregler.

Hvis et program endrer strukturen og innholdet til et XML-dokument og produserer et nytt dokument, kan det være bedre og enklere å bruke et stilark for å håndtere arbeidet i stedet for å skrive et Java-program som gjør den samme jobben. Stilarket er mest sannsynlig lagret i en ekstern fil, slik at du kan endre det på farten, uten behov for å kompilere på nytt.

For eksempel kan vi utføre behandlingen for adressebok prøve ved å lage et stilark som fletter den bufrede versjonen av adressebok med den oppdaterte, og dermed opprette et nytt dokument med oppdateringene i.

Her er et utvalg av et slikt stilark:

   //mymachine.com/changed.xml 
$config[zx-auto] not found$config[zx-overlay] not found