XML - ćwiczenia 7 - XSLT

Patryk Czarnik

Utworzono: 2002.11.17

Zmodyfikowano: 2002.11.19

Referencje

Rekomendacje

XSLT
XPath
XSL

Narzędzia

Procesory XSLT:
Xalan (Java, projekt Apache)
Xalan (C++, projekt Apache)
libxml (C, Linux, projekt Gnome)
Sablotron (C, różne platformy)
Internet Explorer i wiele programów pod Windows korzysta z biblioteki MSXML.

Dokumentacja JAXP - standard określa m.in. jaki interfejs powinny mieć procesory XSLT w Javie.
API pakietu javax.xml.transform - standardowy pakiet do transformacji w Javie 1.4.

W naszym labie działa takie polecenie:
java org.apache.xalan.xslt.Process -XSL szablon.xsl -IN wejscie.xml -OUT wynik.html

Struktura arkusza XSLT

element główny:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

konfiguracja arkusza:
  <xsl:output method="html" encoding="iso-8859-2" />
  <xsl:import href="inny_arkusz.xsl"/>

szablony:
  <xsl:template match="/">
    <html><body><xsl:apply-templates/></body></html>
  </xsl:template>

  <xsl:template match="podelement">
    <p><xsl:value-of select="."/></p>
  </xsl:template>
</xsl:stylesheet>

Pattern matching

Atrybut match w elemencie template mówi do jakich węzłów dany szablon będzie aplikowany. Jego wartością powinien być pattern - coś na kształt ścieżki XPath. Ten sam węzeł może pasować do wielu szablonów i ich pól match. Wówczas intuicyjnie wybierany jest ten szablon, który najbardziej precyzyjnie określa dany węzeł, a w ostateczności liczy się kolejność deklaracji szablonów - dokładnie opisuje to rekomendacja.

Tworzenie dokumentu wynikowego

Do tworzenia poszczególnych węzłów dokumentu wynikowego służą odpowiednie elementy szablonu:

<xsl:element name="elem">
  <xsl:attribute name="atryb">wartość atrybutu</xsl:attribute>
  <xsl:text>Zawartość tekstowa</xsl:text>
  <xsl:text disable-output-escaping="yes"><a href="adres">super!</a></text>
</xsl:element>
<xsl:comment>To będzie komentarz</xsl:comment>
<xsl:processing-instruction target="xml-stylesheet">type="text/css" href="styl.css"</xsl:processing-instruction>

Do tworzenia poszczególnych węzłów dokumentu wynikowego służą odpowiednie elementy szablonu:

<xsl:element name="elem">
  <xsl:attribute name="atryb">wartość atrybutu</xsl:attribute>
  <xsl:text>Zawartość tekstowa</xsl:text>
  <xsl:text disable-output-escaping="yes"><a href="adres">super!</a></text>
</xsl:element>
<xsl:comment>To będzie komentarz</xsl:comment>
<xsl:processing-instruction target="xml-stylesheet">type="text/css" href="styl.css"</xsl:processing-instruction>

Można też po prostu wpisywać fragmenty wynikowego dokumentu jako XML (ale nie wszystko da się tak wyrazić).

<elem atryb="wartość atrybutu">
  Zawartość tekstowa <xsl:text disable-output-escaping="yes"><a href="adres">super!</a></text>
<elem>
<xsl:comment>To będzie komentarz</xsl:comment>
<xsl:processing-instruction target="xml-stylesheet">type="text/css" href="styl.css"</xsl:processing-instruction>

Aby utworzyć węzeł taki sam jak węzeł bieżący, można użyć elementu copy. Domyślnie kopiowanie jest powierzchowne, aby skopiować również atrybuty i podelementy trzeba to zrobić "ręcznie" wewnątrz copy. Węzłem bieżącym może być nie tylko element, ale też np. atrybut, węzeł tekstowy.

<xsl:copy> <xsl:apply-templates/> </xsl:copy>

Sterowanie

XSLT dostarcza konstrukcji do pisania wyrażeń warukowych (if, choose>) oraz iterowania po węzłach z wartości typu node-set (for-each). Wewnątrz for-each zmienia się węzeł bieżący.

<xsl:if test="$x < 1">x jest mniejsze od 1</xsl:if>
<xsl:choose>
  <xsl:when test="$x = 1">x równe 1</xsl:when>
  <xsl:when test="$x = 2">x równe 2</xsl:when>
  <xsl:otherwise>x różne od 1 i 2</xsl:otherwise>
</xsl:choose>
<xsl:for-each select="row[position() >= 2]">kolejny wiersz</xsl:for-each>

Wyrażenia XPath w XSLT

Aby wstawić do dokumentu wynikowego wartość wyrażenia XPath, można użyć elementu value-of (wstawia tekst) lub copy-of (wstawia drzewo). Niektóre atrybuty elementów XSLT oczekują wartości będących wyrażeniami XPath. Są to np. select - wyrażenia typu node-set, test - wyrażenia typu boolean. W pozostałych atrybutach można wstawić wartość tekstową wyrażenia XPath pisząc {wyrażenie}.

<xsl:for-each select="./tekst">
<p class="{@styl}"><xsl:value-of select="."/></p>
</xsl:for-each>

<!-- trochę to bez sensu, ale trudno: -->
<xsl:for-each select="./table">
<xsl:copy-of select="."/>
</xsl:for-each>

Parametry i zmienne

Arkusz XSLT możan sparametryzować nazwanymi parametrami. Trzeba je zadeklarować na najwyższym poziomie arkusza. Do ich wartości można się później odwoływać za pomocą $nazwa.
Można też deklarować "zmienne" i odwoływać się do ich wartości, z tym że są to zmienne "deklaratywne" analogicznie do konstrukcji let x = wyrażenie in wyrażenie z języków funkcyjnych.

<xsl:stylesheet ... >
<xsl:param name="x" select="0"/>
<xsl:template match="/">
  ...
  <xsl:variable name="y" select="number/@val"/>
  ...
  <xsl:if test="$x < $y"> bla bla </xsl:if>
</xsl:template>
</xsl:stylesheet>

Dwa style przetwarzania dokumentów

Sposób tworzenia dokumentu wynikowego zależy od inwencji autora XSLT :), ale można wyróżnić dwa zasadnicze style:

  1. Przetwarzanie ukierunkowane na strukturę dokumentu wejściowego - wiele małych szablonów dla poszczególnych elementów i innych węzłów dokumentu wejściowego, strutura wynikowa nie jest jednoznacznie ustalona. Nadaje się do przetwarzania dokumentów o nieustalonej strukturze, modelu mieszanego.
  2. Przetwarzanie ukierunkowane na strukturę dokumentu wynikowego - jeden duży szablon, określający dokładnie strukturę wynikową a do dokumentu wejściowego odwołujący się za pomocą (często bezwzględnych) ścieżek XPath, elementów for-each. Dobry do przetwarzania dokumentów o dobrze znanej strukturze, gdy wynik musi mieć ściśle określoną strukturę.
Często miesza się oba style. Np. tworząc HTML stylem "wynikowym" tworzy się nagłówki i elementy o ściśle określonej strukturze (tabele, na ogół formularze), a gdy dokument wejściowy zawiera gdzieś model mieszany, stylem "wejściowym" tworzy się zawartość tekstową z możliwymi zanurzonymi elementami formatującymi.

Przykłady i zadania

przykład studenci

  1. Niech arkusz wybiera tylko tylko studentów z pierwszej grupy.
  2. Wprowadź parametr określający numer grupy, z której studentów ma wybierać arkusz. Jeśli nie zostanie podany, mają być wybierani wszyscy.
  3. Wyświetlaj kursywą nazwiska studentów, których status jest równy prosba.
  4. Utwórz nowy arkusz tworzący plik XML o takiej samej strukturze, ale wybierający tylko studentów z danej grupy (parametr) i sortujący ich według nazwisk.

przykład arkusz do tej strony

  1. Niech na początku strony wyświetla się spis treści (spis wszystkich elementów section).
  2. Niech nzawisko autora będzie wyświetlane jako link do jego adresu e-mail (o ile jest podany).

źródło w XML