Dokonamy teraz przeglądu instrukcji XSLT. Wszystkie one mają podobną budowę:

  • nazwa instrukcji (tagu)
  • atrybut select/match precyzujący obiekt na jaki działać ma instrukcja

xsl:for-each

Pozwala na przetwarzanie elementów wybranych przez atrybut select. Dla każdego elementu spełniającego frazę select zostaje wykonane "ciało" instrukcji a więc zawartość elementu xsl:for-each.

Działanie instrukcji for-each jest dualne do pary apply-templates i templates. Naprzykład:

  <xsl:template match="PERIODIC_TABLE">
    <xsl:for-each select="ATOM">
      <xsl:value-of select="."/>
    </xsl:for-each>
  </xsl:template>

Spowoduje wypisanie wszystkich elementów "ATOM' z poddrzew "PERIODIC_TABLE". Efekt ten można również uzyskać poprzez:

  <xsl:template match="PERIODIC_TABLE">
    <xsl:apply-templates select="ATOM"/>
  </xsl:template>

  <xsl:template match="ATOM">
    <xsl:value-of select="."/>
  </xsl:template>

Wzorce dla atrybutów

Wyobraźmy sobie, że chcemy przekształcić informację o atomach z postaci gdzie każda cecha trzymana była jako osobny element poddrzewa na wersję gdzie będą to atrybuty węzła atom:

<ATOM NAME="Vanadium"
  ATOMIC_WEIGHT="50.9415"
  ATOMIC_NUMBER="23"
  OXIDATION_STATES="5, 4, 3, 2"
  BOILING_POINT="3650K"
  MELTING_POINT="2163K"
  SYMBOL="V"
  DENSITY="6.11 grams/cubic centimeter"
/>

Niestety nie da się tego zrobić w pierwszy nasuwający się sposób, ponieważ taki wzorzec nie jest poprawnym elementem XML'a

<xsl:template match="ATOM">
    <ATOM NAME="<xsl:value-of select='NAME'/>"
    ATOMIC_WEIGHT="<xsl:value-of select='ATOMIC_WEIGHT'/>"
    ATOMIC_NUMBER="<xsl:value-of select='ATOMIC_NUMBER'/>"
  />
</xsl:template>

Została wprowadzona notacja {} która odpowiada xsl:value-of o ile umieszczona zostanie w miejscu atrybutu.

<xsl:template match="ATOM">
  <ATOM NAME="{NAME}"/>
    ATOMIC_WEIGHT="{ATOMIC_WEIGHT}"
    ATOMIC_NUMBER="{ATOMIC_NUMBER}"
  />
</xsl:template>

Fraza {NAME} jest tutaj równoważna <xsl:value-of select="NAME"/>. Możliwe są bardziej skomplikowane konstrukcje, można bowiem korzystać z dowolnych wyrażeń XPath. Jak również łączyć wyrażenia ze statycznym tekstem.

<xsl:template match="ATOM">
  <A HREF="{SYMBOL}.html">
    <xsl:value-of select="NAME"/>
  </A>
</xsl:template>

<xsl:template match="DENSITY">
  <BULK_PROPERTY
    NAME="DENSITY"
    ATOM="{../NAME}"
    VALUE="{normalize-space(.)} {@UNITS}"
  />
</xsl:template>

xsl:element

Zazwyczaj by umieścić element XML'a w wynikowym dokumencie wystarczy umieścić go w odpowiednim wzorcu tak jak robiliśmy to z tagami <html> czy <body> Czasem jednak pojawia się potrzeba umieszczenia elementu którego nazwa znana jest dopiero w czasie przetwarzania dokumentu. Służy do tego właśnie instrukcja xsl:element która wprowadza tag o nazwie takiej jak jej atrybut name, zaś wartością nowego elementu jest zawartość instrukcji.

<xsl:template match="ATOM">
  <xsl:element name="{@STATE}">
    <NAME><xsl:value-of select="NAME"/></NAME>
  </xsl:element>
</xsl:template>

Tworzy element o nazwie będącą wartością atrybutu STATE, a więc otrzymamy

<GAS>
  <NAME>Hydrogen</NAME>
</GAS>
<SOLID>
  <NAME>Sodium</NAME>
</SOLID>

xsl:attribute

Tak jak xsl:element pozwala na dodawanie elementów o danej nazwie tak xsl:attribute umożliwia dodawanie nowych atrybutów o nazwie takiej jak jego parametr name.

<xsl:template match="ATOM">
  <LI><A>
    <xsl:attribute name="HREF">
      <xsl:value-of select="SYMBOL"/>.html
    </xsl:attribute>
    <xsl:value-of select="NAME"/>
  </A></LI>
</xsl:template>	

Należy wspomnieć tu o ważnym ograniczeniu, wszystkie atrybuty muszą pojawić się przed innymni instrukcjami w węźle.

xsl:attribute-set

Istnieje możliwość zdefiniowana często występujących atrybutów jako zbioru dostępnego w całym arkuszu i dołączanie ich do tworzonych elementów. Zbiór atrybutów definiuje się instrukcją xsl:attribute-set

<xsl:attribute-set name="cellstyle">
  <xsl:attribute name="font-family">
    New York, Times New Roman, Times, serif
  </xsl:attribute>
  <xsl:attribute name="font-size">12pt</xsl:attribute>
</xsl:attribute-set> 

Korzysta się z nich poprzez wymienienie atrybutu xsl:use-attribute-sets w nowo tworzonym elemencie. Można umieszczać kilka zbirów atrybutów poprzez podanie ich nazw rozdzielonych spacją.

<xsl:template match="ATOM">
  <tr>
    <td xsl:use-attribute-sets="cellstyle">
      <xsl:value-of select="NAME"/>
    </td>
    <td xsl:use-attribute-sets="cellstyle">
      <xsl:value-of select="ATOMIC_NUMBER"/>
    </td>
  </tr>
</xsl:template>

<td xsl:use-attribute-sets="cellstyle numberstyle">
  <xsl:value-of select="ATOMIC_NUMBER"/>
</td>

W przypadku xsl:element pomijana jest część xsl atrybutu

 <xsl:element name="td" use-attribute-sets="cellstyle">
   <xsl:value-of select="ATOMIC_NUMBER"/>
 </xsl:element>

xsl:processing-instruction

Pozwala na umieszczenie instrukcji procesora w wynikowym dokumencie

<xsl:template match="PROGRAM">
  <xsl:processing-instruction name="gcc">-O4 
    <xsl:value-of select="NAME"/>
  </xsl:processing-instruction>
</xsl:template>

xsl:comment

Wprowadza komentarze do wyjściowego dokumentu.

<xsl:template match="ATOM">
  <xsl:comment>There was an atom here once.</xsl:comment>
</xsl:template>

xsl:text

Pozwala na umieszczanie tekstu w wynikowym dokumencie. Korzyści jakie oferuje ten element są dwie:

  • zachowuje białe znaki
  • pozwala na umieszczenie znaków < i > w wynikowym tekście poprzez zastąpienie sekwencji &lt; czy &amp

<xsl:template match="SCRIPT">
 <script language="javascript">
  <xsl:text disable-output-escaping="yes">
    <!-- if (
     location.host.toLowerCase().indexOf("metalab") < 0 
     && location.host.tolowercase().indexof("sunsite") < 0) {
     location.href="http://metalab.unc.edu/xml/";
     }
    } // -->
  </xsl:text>
 </script>
</xsl:template>

xsl:copy

Kopiuje bieżący węzeł, ale nie robi tego z jego atrybutami i dziećmi. Zawartość elementu xsl:copy jest jednak traktowana jako wzorzec, możliwe jest więc kolejne kopiowanie elementów.

Przedstawiony arkusz kopiuje dokument, ale wycinając komentarze.

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

  <xsl:template match="*|@*|processing-instruction()|text()">
    <xsl:copy>
      <xsl:apply-templates 
        select="*|@*|processing-instruction()|text()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

xsl:number

Pozwala na umieszczenie sformatowanej liczby z atrybutu value w zależności od parametru format.

<xsl:template match="ATOM">
  <td><xsl:number value="position()"/></td>
  <td><xsl:value-of select="NAME"/></td>  
</xsl:template>

Jeśli parametr value zostanie pominięty stosowana będzie domyślnie pozycja elementu w drzewie (a więc tak samo jak w przykładzie powyżej). Istnieją jednak atrybuty pozwalające dostosować proces zliczania, są to

  • level
  • count
  • from

Atrybut level pozwala na ustalenie jak należy zliczać elementy, jeśli zostanie pominięty zliczane jest tylko rodzeństwo danego węzła (i to wybrane), jeśli jednak zostanie ustawiony na "any" zliczone zostaną wszystkie węzły danego typu w dokumencie, nawet jeśli nie stosuje się do nich żadna reguła.

Atrybut count precyzuje jakie elementy mają być zliczane (standardowo takiego typu jak bieżący).

<xsl:template match="ATOM/*">
  <td><xsl:number count="*"/></td>
  <td><xsl:value-of select="."/></td>
</xsl:template>

Atrybut from decyduje o tym od jakiego elementu rozpoczynać ma się zliczanie, będzie jednak ono zawsze zaczynać się od 1

O tym jaki format ma przyjąć wyliczanie decydują następujące atrybuty

  • format
  • letter-value
  • grouping-separator
  • grouping-size

Atrybut format decyduje o tym jaki system numeracji zostanie zastosowany. Jeśli jest on pominięty pojawia się arabska liczba, dopuszczalne są ponadto następujące wartości

  • i - jako wynik pojawiaja się rzymskie liczby: i, ii, iii, iv....
  • I - jako wynik pojawiaja się rzymskie liczby: I, II, III, IV...
  • a - jako wynik pojawiają się litery: a, b, c, d ....
  • A - jako wynik pojawiają się litery: A, B, C, D

Atrybuty grouping-separator i grouping-size pozwalają na ustalenie jak mają być prezentowane duże liczby. Pierwszy z nich ustala jaki znak ma się pojawiać pomiędzy grupami na przykład grouping-separator="." spowoduje że pojawi się liczba 123.000.001 zamiast 1230000001. Parametr grouping-size informuje po ile grupowane mają być cyfry.

xsl:sort

Element ten pozwala na ustalenie kolejności elementów poddawanych obróbce w kolejności innej niż w źródłowym dokumencie. Występuje on wewnątrz elementów xsl:apply-templates i xsl:for-each modyfikując kolejność w jakim pasujące węzły będą poddawane obróbce.

Atrybut select elementu xsl:sort ustala klucz po jakim ma następować sortowanie. Jeśli występuje więcej niż jeden element xsl:sort, sortowanie następuje najpierw po pierwszym kluczu, potem według drugiego itd. Domyślnie sortowanie odbywa się w porządku alfabetycznym, ale możliwa jest zmiana poprzez ustawienie atrybutu data-type.

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

  <xsl:template match="PERIODIC_TABLE">
    <html>
      <head>
        <title>Atomic Number vs. Atomic Weight</title>
      </head>
      <body>
        <h1>Atomic Number vs. Atomic Weight</h1>
        <table>
          <th>Element</th>
          <th>Atomic Number</th>
          <th>Atomic Weight</th>
          <xsl:apply-templates>
            <xsl:sort select="ATOMIC_NUMBER" data-type="number"/>
          </xsl:apply-templates>
        </table>
      </body>
    </html>
  </xsl:template>
  
  <xsl:template match="ATOM">
    <tr>
      <td><xsl:apply-templates select="NAME"/></td>
      <td><xsl:apply-templates select="ATOMIC_NUMBER"/></td>
      <td><xsl:apply-templates select="ATOMIC_WEIGHT"/></td>
    </tr>
  </xsl:template>
  
</xsl:stylesheet>

Dzięki atrybutowi order i wartości "descending" możliwa jest zamiana kolejności sortowania.

<xsl:sort order="descending"
          data-type="number" 
          select="ATOMIC_NUMBER"/>

xsl:variable

Element xsl:variable pozwala zdefiniować zmienną o nazwie będącej wartością atrybutu name. Wartością zmiennej może być zarówno zwykły tekst, jak i element wzorca, tak, że faktyczna wartość zmiennej będzie wyliczana w zeleżności od bieżącego miejsca w dokumencie. Niedozwolone jest jednak odwoływanie się rekurencyjne do zmiennych zarówno bezpośrednie jak i pośrednie.

<xsl:variable name="copy99">
  Copyright 1999 Elliotte Rusty Harold
</xsl:variable>

<xsl:variable name="Thing1">
  Thing1 loves <xsl:value-of select="NAME"/>
</xsl:variable>
			

Do zmiennej odwołujemy się poprzez poprzedzenie jej nazwy znakiem $. Zmienne mogą być globalne jeśli znajduję na pierwszym poziomie drzewa dokumentu XSLT lub lokalne jeśli zostały zadeklarowane wewnątrz elementu xsl:template.

<BLOCK COPYRIGHT="{$copy99}">
</BLOCK >

<xsl:variable name="Thing2">
  Thing2 loves <xsl:value-of select="$Thing1"/>
</xsl:variable>
			

xsl-if

Element xsl-if pozwala na warunkowe wykonanie bloku wzorca. jeśli wyrażenie XPath będące wartością atrybutu test ewaluuje do true wykonywane są instrukcje zawarte w elemencie xsl-if.

<xsl:template match="ATOM">
  <xsl:value-of select="NAME"/>
  <xsl:if test="position()!=last()">, </xsl:if>
</xsl:template>

xsl-choose

Element xsl-choose pozwala na wybór akcji jaka ma być podjęta. Zawiera on zbiór elementów xsl-when których atrybut test podlega obliczeniu i jeśli wynikiem jest true wykonywany jest blok w nich zawarty. Jeśli więcej niż jeden warunek jest prawdziwy wykonuje się pierwszy w kolejności.

<xsl:template match="ATOM">
  <xsl:choose>
    <xsl:when test="@STATE='SOLID'">
      <P style="color:black">
        <xsl:value-of select="."/>
      </P>
    </xsl:when>
    <xsl:when test="@STATE='LIQUID'">
      <P style="color:blue">
        <xsl:value-of select="."/>
      </P>
    </xsl:when>
    <xsl:when test="@STATE='GAS'">
      <P style="color:red">
        <xsl:value-of select="."/>
      </P>
    </xsl:when>
    <xsl:otherwise>
      <P style="color:green">
        <xsl:value-of select="."/>
      </P>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

xsl:import

Pozwala na zaimportowanie arkuszy xsl z pod adresu przechowywanego w atrybucie href. Elementy takie muszą pojawić się przed elementami xsl:template. Jeśli kilka arkuszy definiuje sprzeczne reguły, obowiązuje reguła z ostatniego elemenu xsl:import, która i tak ustępuje regułom bezpośrednio zdefiniowanym w arkuszu.

<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="genealogy.xsl"/>
  <xsl:import href="standards.xsl"/>
  <!-- other child elements follow -->
</xsl:stylesheet>			

xsl:include

Element ten powoduje wstawienie w miejscu jego wystąpienie reguł pobranych ze wskazanej przez atrybut href lokalizacji. Reguły te traktowane są tak jakby fizycznie znajdowały się w bieżącym arkuszu.