XPATH
XSLT
Børre Stenseth

XPath

Hva

Vi har støtt på behovet for å orientere oss i et dokuments trestruktur flere ganger når vi skriver XSLT-kode. Den uttrykksformen vi bruker for å gjøre dette kalles XPath. XPath ble opprinnelig laget som en del av XSL, men ble generalisert som en egen anbefaling fordi den er generelt nyttig for navigering i trær.

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.

I moderne browsere kan vi bruke XPath fra JavaScript.

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".

Vi kan sette sammen flere sekvenser av denne typen i ett uttrykk.

child::bok[position()=1]/side[position()=1]/text()
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.

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 noen av dem. Du kan jo kikke på Xpath Visualizer [1] .

Referanser
  1. Xpath Visualizer CodePlex xpathvisualizer.codeplex.com/ 14-02-2014
  1. XPath 1.0 W3C www.w3.org/TR/xpath 14-03-2014
  1. XPath 2.0 W3C www.w3.org/TR/xpath20 14-03-2014
  1. Introduction to using XPath in JavaScript MDN developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript 14-12-2015