XPath
Problemstillingen
Vi vet at XSLT hele tiden arbeider mot en trestruktur, som i all hovedsak er slik vi kjenner den fra DOM.
Når vi navigerer i et slikt tre må vi til en hver tid ha klart for oss hvor vi er, og vi må kunne få tak i elementer eller attributter som er andre steder i treet.
Form
Et XPath uttrykk kan bestå av inntil tre deler: Axis, nodetest og predicate. F.eks.:
child::bok[position()=1]
som angir "det første elementet av typen bok som er barn av kontekstnoden".
| child | axis angir hva slags relasjon vi ønsker i forhold til kontekstnoden |
| bok | nodetest angir hva slags type node vi er interesserte i |
| position()=1 | predicate plukker ut et utvalg av de nodene vi har kvalifisert ved axis og nodetest |
Axes
Når vi ønsker å velge ut et sett med noder i en select-atributt i kommandoene: xsl:apply-templates, xsl:value-of, xsl:for-each, xsl:copy-of, xsl:variable, xsl:param, xsl:sort, så kan vi bruke følgende uttrykk for å navigere i treet i forhold til kontekstnoden:
| ancestor | Forfedre til kontekstnoden |
| ancestor-or-self | Forfedre til kontekstnoden og kontekstnoden selv |
| attribute | Attributt til kontekstnoden |
| child | Barn av konteksnoden |
| descendant | Etterkommere av kontekstnoden |
| descendant-or-self | Etterkommere av kontekstnoden og kontekstnoden selv |
| following | Elementer som begynner etter konteksnoden |
| following-sibling | Etterfølgende søsken til kontekstnoden |
| namespace | Elementer som er i angitt namespace og er etterkommere av kontekstnoden |
| parent | Far til kontekstnoden |
| preceding | Elemeneter som er avsluttet før kontekstnoden |
| preceding-sibling | Tidligere søsken til kontekstnoden |
| self | Konteksnoden |
Eksempelliste
oversatt fra W3C.
Med kontekstnoden i oversikten nedenfor mener vi den noden vi "befinner oss på", altså den vi skal orientere oss i forhold til i dokumenttreet.
| XPath-uttrykket: | velger ut: |
|---|---|
| child::para | alle elementer av typen para som er barn av kontekstnoden |
| child::* | alle elementer som er barn av kontekstnoden |
| child::text() | alle tekstnoder som er barn av kontekstnoden |
| child::node() | alle barn av kontekstnoden, uansett type |
| attribute::name | attributten name til kontekstnoden |
| attribute::* | alle attributter til kontekstnoden |
| descendant::para | alle elementene para som er etterkommere (barn, barnebarn etc) av kontekstnoden |
| ancestor::div | alle elementene div som er forfedre (foreldre, besteforeldre etc.) til kontekstnoden |
| ancestor-or-self::div | alle elementene div som er forfedre og kontekstnoden selv hvis den er av typen div |
| descendant-or-self::para | alle elementer av typen para som er etterkommere og kontekstnoden selv hvis den er av typen para |
| self::para | kontekstnoden dersom den er av typen para, ellers ikke noe |
| child::chapter/descendant::para | alle elementene av typen para som er etterkommere av barn til kontekstnoden som er av typen chapter |
| child::*/child::para | alle barnebarn av kontekstnoden som er av typen para |
| / | dokumentets rot |
| /descendant::para | alle elementer av typen para i samme dokument som kontekstelementet |
| /descendant::olist/child::item | alle elementer av typen item som har et element av typen olist som far, og som er i samme dokument som kontekstnoden |
| child::para[position()=1] | det første elementet av typen para som er barn av kontekstnoden |
| child::para[position()=last()] | det siste elementet av typen para som er barn av kontekstnoden |
| child::para[position()=last()-1] | det nest siste elementet av typen para som er barn av kontekstnoden |
| child::para[position()>1] | alle elementene av typen para som er barn av konteksnode, untatt det første |
| following-sibling::chapter[position()=1] | det neste elementet av typen chapter som er søsken til kontekstnoden |
| preceding-sibling::chapter[position()=1] | det forrige elementet av typen chapter som er søsken til kontekstnoden |
| /descendant::figure[position()=42] | det 42. elementet av typen figure i dokumentet |
| /child::doc/child::chapter[position()=5]/child::section[position()=2] | det andre elementet av typen section i det femte elementet av typen chapter i elementet av typen doc |
| child::para[attribute::type="warning"] | alle elementer av typen para som er barn av kontekstnoden og som har attributt med navn type og med verdi warning |
| child::para[attribute::type='warning'][position()=5] | det femte elementet av type para som er barn av kontekstnoden og som har en attributt med navn type og verdi warning |
| child::para[position()=5][attribute::type="warning"] | det femte elementet av type para som er barn av kontekstnoden hvis det har en attributt med navn type og verdi warning |
| child::chapter[child::title='Introduction'] | alle elementer av typen chapter som er barn av kontekstnoden og som har en eller fler barn av typen title med innholdet Introduction |
| child::chapter[child::title] | alle barn av kontekstnoden som er av typen chapter og som har en eller flere barn av typen title. |
| child::*[self::chapter or self::appendix] | alle barn av kontekstnoden som er elemenetr av typen chapter eller appendix |
| child::*[self::chapter or self::appendix][position()=last()] | det siste elmentet av typen chapter eller appendix som er barn av kontekstnoden |
Kortformer
| . | self::node() |
| .. | parent::node() |
| name | child::name |
| @name | attribute::name |
| // | /descendant-or-self::node()/ |
Noen XPathfunksjoner
Her finner du noen funksjoner som fungerer i XPath-uttrykk. Lista er ikke komplett. Jeg har tatt med de du trolig først vil ha behov for. En full liste finner du selvsagt hos W3C.
| Disse opererer på node set, en gruppe noder | ||
|---|---|---|
| position() | number | Posisjonen til kontekstnoden i det aktuelle nodesettet |
| last() | number | Antall noder i det aktuelle nodesettet |
| count(nodeset) | number | Antall noder i parameter |
| id(string) | nodeset | En node med element id lik string hvor som helst i det samme dokumentet. String kan også være en kommaseparert liste med id-verdier. |
| String funksjoner | ||
| concat() | string | Slår sammen stringer som angis som parametere. collect('hallo','der') |
| contains() | boolean | Returnerer true hvis en a inneholder b. contains(a,b) |
| normalize-space() | string | Trimmer en string for whitespace. |
| starts-with() | boolean | Returnerer true hvis a begynner med b. starts-with(a,b) |
| string() | string | Returnerer a som string. string(2) gir '2' |
| string-length() | number | Returnerer lengden til en string |
| substring() | string | Returnerer et utdrag fra en string. substring(hele,startix,lengde) |
| substring-after() | string | Returnerer et utdrag fra en string. substring-after('kr10/kg','/') gir 'kg' |
| substring-before() | string | Returnerer et utdrag fra en string. substringbefore('kr10/kg','/') gir 'kr10' |
| translate() | string | Gjør en replace. translate('hello','e','a') gir 'hallo' |
| Tall funksjoner | ||
| ceiling() | number | Returnerer det det minste heltallet større enn argumentet. ceiling(2.1) gir 3 |
| floor() | number | Returnerer det det største heltallet mindre enn argumentet. floor(2.1) gir 2 |
| number() | number | Oversetter en string til et tall. |
| round() | number | Avrunder et tall til nærmeste heltall. |
| sum() | number | Summerer numeriske verdier i et nodesett. |
Noen Verktøy
Det finnes noen nyttige verktøy for å eksperimentere med XPath. Disse er nyttige både i opplæring og i utviklingsarbeid. Jeg har lastet ned og testet to av dem. Begge er gratis.
XPath Visualizer
Xpath Visualizer [1]
XPath Explorer
XPath Explorer [2] er skrevet i java og distribuert som jar. Kildekoden er også tilgjengelig. Kjøres slik: java -jar xpe.jar fra kommandolinja.