XSL - Übersicht / xsl:variable

xsl:variable

xsl:variable

Im XSL übernimmt eine Variable nur einen temporären Inhalt, der in der Regel zur Laufzeit gesetzt und an passender anderer Stelle wieder ausgelesen wird. Dieser temporäre Inhalt kann einen einzelnen Wert, eine Liste simplen Datentyps sein, ebenso ein externes XML-Dokument (document()), ein komplexer Baum, das Zwischenergebnis einer mehrstufigen Konvertierung: mithin eine komplexe Sequenz (xsl:sequence) von Items.

xsl:variable

Im Unterschied zu Variablen in C, C++, C#.NET, Java, VB.NET und zahlreichen anderen Programmiersprachen, in denen ein x = x + 1 eine durchaus sinnvolle Anweisung ist, übernimmt eine Variable in XSL nur einen temporären Wert, der in der Regel zur Laufzeit gesetzt und an passender anderer Stelle wieder ausgelesen wird.


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">
  <xsl:output method="xml" indent="yes" />

Über die "document"-Funktion können externe XML-Dokumente (die ausdrücklich nicht Teil des XML-Inputs sind) in eine Variable eingelesen werden. Damit umfaßt die Variable $vinput" einen komplexen XML-Baum.


  <xsl:variable name="vinput"
    select="document('Orte_Elemente.xml')" />

$var1 greift auf den $vinput zu; durch die gezielte XPath-Adressierung beinhaltet $var1 einen normalen Textinhalt.


  <xsl:variable name="var1"
    select="$vinput/Orte/Ort[1]/Mensch[2]/Kauf[3]/bez/text()" />

$var2 greift ebenfalls auf $vinput zu. Der Inhalt umfaßt ein einziges Element, das seinerseits mehrere Childnodes in sich birgt. Um diese anzusteuern, ist in XPath $var2/Kauf/child::* erforderlich. Die Einzelinformation erhalten wir über $var2/Kauf/bez.


  <xsl:variable name="var2">
    <xsl:copy-of select="$vinput/Orte/Ort[1]/Mensch[2]/Kauf[3]" />
  </xsl:variable>

$var3 greift ebenfalls auf $vinput zu. Bedingt durch die XPath-Adressierung, umfaßt $var3 mehrere Childnodes: hier werden mehrere Childnodes direkt zugewiesen, ohne das kapselnde Element Kauf. Angesteuert werden können diese im Loop über $var3/child::*. Die Einzelinformation erhalten wir über $var3/bez.


  <xsl:variable name="var3">
    <xsl:for-each 
    select="$vinput/Orte/Ort[1]/Mensch[2]/Kauf[3]/child::*">
      <xsl:copy-of select="." />
    </xsl:for-each>
  </xsl:variable>

Das benannte Template "NodeInfo" untersucht den jeweils aktuellen Node / Kontext aus verschiedener Sicht. Wir beachten, daß das Template "NodeInfo" keine Parameterzuweisung umfaßt, sondern den Kontext ausschließlich zur Laufzeit zugewiesen bekommt.


  <xsl:template name="NodeInfo">
    <xsl:attribute name="Elementname" select="./local-name()" />
    <xsl:attribute name="wert" select="." />
    <xsl:attribute name="Nodetype">
    <xsl:choose>
      <xsl:when test="./self::text()">Textnode</xsl:when>
      <xsl:when test="./self::element()">Elementnode</xsl:when>
      <xsl:when test="./self::comment()">Kommentarknoten</xsl:when>
    </xsl:choose>
    </xsl:attribute>
    <xsl:attribute name="XSDtype">
      <xsl:choose>
      <xsl:when test=". castable as xs:integer">xs:integer</xsl:when>
      <xsl:when test=". castable as xs:decimal">xs:decimal</xsl:when>
      <xsl:when test=". castable as xs:string">xs:string</xsl:when>
      </xsl:choose>
    </xsl:attribute>
  </xsl:template>

<xsl:template match="/"> definiert in diesem Fall den Programmstart. Hier werden die vorher deklarierten Variablen angesprochen und jedes ihrer Childnodes über eine Schleife dem vorher benannten Template "NodeInfo" übergeben, das die restliche Arbeit übernimmt.


  <xsl:template match="/">
    <ergebnis>
      <var1>
        <xsl:for-each select="$var1/self::text()">
          <xsl:call-template name="NodeInfo" />
        </xsl:for-each>
      </var1>
      <var2>
        <xsl:for-each select="$var2/Kauf/child::*">
          <childelement>
            <xsl:call-template name="NodeInfo" />
          </childelement>
        </xsl:for-each>
      </var2>
      <var2bez>
        <xsl:value-of select="$var2/Kauf/bez"/>
      </var2bez>
      <var3>
        <xsl:for-each select="$var3/child::*">
          <childelement>
            <xsl:call-template name="NodeInfo" />
          </childelement>
        </xsl:for-each>
      </var3>
      <var3bez>
        <xsl:value-of select="$var3/bez"/>
      </var3bez>
    </ergebnis>
  </xsl:template>
</xsl:stylesheet>

xsl:sequence

Eine weitere Alternative zur Variablendeklaration bietet xsl:sequence:


  <xsl:variable name="vsequence">
    <xsl:sequence select="//Mensch/vorname"/>
  </xsl:variable>
  <xsl:for-each select="$vsequence/child::*">
    <vn>
      <xsl:value-of select="."/>
    </vn>
  </xsl:for-each>   

Wie , ist es sinnvoll, sich über den Datentyp von Variablen jeweils genau im Klaren zu sein, um Programmierfehler mit weitreichenden Konsequenzen zu vermeiden.

Siehe auch:

xsl:document

Eine weitere Alternative zur Variablendeklaration bietet xsl:document. Wie in besprochen, können Elemente mittels xsl:validation auch einer XML Schema-Validierung unterzogen werden (einen schema-aware-processor vorausgesetzt).


<xsl:import-schema 
  use-when="system-property('xsl:is-schema-aware') eq 'yes'
  schema-location="../xsd/tempTreeOrte.xsd"/>
<xsl:variable name="vOrte_from_tab" as="item()">
  <Orte xsl:validation="strict">
  </Orte>
</xsl:variable>

Dieser Ansatz funktioniert auch mit xsl:document:


  <xsl:variable name="vdocument">
    <xsl:document validation="strict">
      <Orte>
        ...
      </Orte>
    </xsl:document>
  </xsl:variable>

Anonyme Funktionen

In XSL 3.0 ist es auch möglich, eine Variable als zu deklarieren.

wg / 14. Januar 2018



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf:

Vorname
Nachname
Mailadresse







Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

Mobil: 0151. 750 360 61 * eMail: info2018@wilfried-grupe.de

www.wilfried-grupe.de/xsl_variablen.html