Home
Über mich
Veröffentlichungen

XML XML-Schema XPath XSL-T XSL-FO XQuery XProc SVG

XSL-T / Die XSLT - Struktur / xsl:element

xsl:element

xsl:element

xsl:element erlaubt die flexible Generierung von XML-Elementen im Zieldokument. Der Vorteil gegenüber fixer Namensdefinition ist, dass der Elementname dynamisch generiert werden kann.

Auf dieser Seite:

Siehe

xsl:element-Syntax in XSLT 1.0:


<xsl:element 
     name = { qualified name }
     namespace = { URI }
     use-attribute-sets = { qualified names }>
</xsl:element>

Siehe auch https://www.w3.org/TR/xslt-10/#element-element.

xsl:element-Syntax in XSLT 2.0 und 3.0:


<xsl:element
  name = { qname }
  namespace? = { uri-reference }
  inherit-namespaces? = "yes" | "no"
  use-attribute-sets? = qnames
  type? = qname
  validation? = "strict" | "lax" | "preserve" | "strip">
  <!-- Content: sequence-constructor -->
</xsl:element>

Siehe auch https://www.w3.org/TR/xslt20/#element-element.

Siehe auch https://www.w3.org/TR/xslt-30/#element-element.

In XSLT ist es einfach, XML-Elemente automatisch zu generieren. Hierfür steht xsl:element mit dem zwingend erforderlichen Attribut name zur Verfügung, das seit XSLT 1.0 bereit steht. Ein häufiger Anwendungsfall hierfür ist die Teilkonvertierrung über xsl:apply-templates.

name Erforderlich, verfügbar seit XSLT 1.0. Hier muss ein qualified name stehen. Er kann auch einen Namespace-Präfix beinhalten.
namespace Optional, verfügbar seit XSLT 1.0. Hier kann ein Namensraum zugewiesen werden. Es kann mit oder ohne Namespace-Präfix deklariert werden. Hier ist ggf. auf unterschiedliche Outputs zu achten.
inherit-namespaces Optional, verfügbar seit XSLT 2.0. Es kann die Werte yes (Default) oder no beinhalten. Hier können Sie festlegen, ob die Namensraum-Knoten weitergegeben werden könnnen.
type Optional, verfügbar seit XSLT 2.0. Hier können Sie den Schema-Datentyp festlegen. Siehe nachfolgendes Beispiel. Das type-Attribut darf nicht zusammen mit dem validation-Attribut verwendet werden.
validation Optional, verfügbar seit XSLT 2.0. Das validation-Attribut darf nicht zusammen mit dem type-Attribut verwendet werden. Siehe auch xs:any, xs:anyType.
use-attribute-sets Optional, verfügbar seit XSLT 1.0. Siehe xsl:attribute-set.

So ergibt der Aufruf in XSLT 2.0


<xsl:template match="/">
  <xsl:element name="wurzel">
    <xsl:element name="stamm">
      <xsl:for-each select="1 to 3">
        <xsl:element name="ast"/>
      </xsl:for-each> 
    </xsl:element>
  </xsl:element>  
</xsl:template>

... oder alternativ:


<xsl:template match="/">
  <wurzel>
    <stamm>
      <xsl:for-each select="1 to 3">
        <ast/>
      </xsl:for-each>        
    </stamm>
  </wurzel>
</xsl:template>

... dieses Resultat:


<wurzel>
  <stamm>
   <ast/>
   <ast/>
   <ast/>
  </stamm>
</wurzel>

Arbeiten mit @namespace

Die lokale Zuweisung eines Namensraums mithilfe des optionalen namespace-Attributes ...


<xsl:template match="/">
    <xsl:element name="wurzel">
        <xsl:element name="wg:stamm"  
            namespace="https://www.wilfried-grupe.de/XSL_element.html">
            <xsl:for-each select="1 to 3">
                <xsl:element name="ast"/>
            </xsl:for-each> 
        </xsl:element>
    </xsl:element>  
</xsl:template>

... erzeugt dieses Resultat:


<wurzel>
   <wg:stamm xmlns:wg="https://www.wilfried-grupe.de/XSL_element.html">
      <ast/>
      <ast/>
      <ast/>
   </wg:stamm>
</wurzel>

Arbeiten mit @type

Das @type-Attribut erlaubt eine verbesserte Typkontrolle in Verbindung mit XML-Schema.


<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <xsl:element name="wurzel">
            <xsl:element name="stamm">
                <xsl:for-each select="1 to 3">
                    <xsl:element name="ast" type="xs:integer">
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:for-each>
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Arbeiten mit @use-attribute-sets

Siehe auch xsl:attribute-set.


<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:attribute-set name="as_Person">
        <xsl:attribute name="nachname">Rielos</xsl:attribute>
        <xsl:attribute name="vorname">Lotte</xsl:attribute>
    </xsl:attribute-set>
    <xsl:template match="/">
        <xsl:element name="Mensch" 
                     use-attribute-sets="as_Person">
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

zaubert dieses Ergebnis:


<Mensch nachname="Rielos" vorname="Lotte"/>

Das XML-Dokument mit xmlns:xsi und Attribut erzeugen

Auch die Einbindung von xmlns:xsi mit xsi:noNamespaceSchemaLocation stellt kein Problem dar:


<xsl:template match="/">
  <wurzel 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="irgendwoImWald.xsd">
    <stamm>
      <xsl:for-each select="1 to 3">
        <ast/>
      </xsl:for-each>        
    </stamm>
  </wurzel>
</xsl:template>

Geht es jedoch darum, den XML-Output samt Zuweisung eines XML-Schema-Dokuments via xsl:element zu erzeugen, ist es guter Stil, xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" in das Root-Element xsl:stylesheet zu verlagern: Anschliessend können Sie mit xsl:attribute arbeiten.


<xsl:stylesheet 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     version="2.0">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <xsl:element name="wurzel">
      <xsl:attribute name="xsi:noNamespaceSchemaLocation">
           irgendwoImWald.xsd
      </xsl:attribute>
      <xsl:element name="stamm">
        <xsl:for-each select="1 to 3">
          <xsl:element name="ast"/>
        </xsl:for-each>
      </xsl:element>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Das Ergebnis sieht in beiden Fällen so aus:


<wurzel 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="irgendwoImWald.xsd">
   <stamm>
      <ast/>
      <ast/>
      <ast/>
   </stamm>
</wurzel>

Konvertierung von Attributen in Elemente

Hilfreich sind auch die Features zur Generierung von Namespaces, Namespace-Prefixes oder zur XML-Schema-basierten Typkontrolle. Das sehen Sie unschwer bei der Konvertierung von Attributen in Elemente. Nehmen Sie das folgende XML-Input-Dokument, dessen einziges Element lediglich Attribute, aber keine Childnodes aufweist.


<Person nachname="Achim" 
        vorname="Achtlos" 
        Geburtsjahr="1970"/>

Gesucht wird nun ein Weg, sämtliche Attribute in eine Ziel-Struktur zu konvertieren, die ausschliesslich Elemente aufweist. Dies wird möglich mit einer Schleife über alle Attribute. Zur Laufzeit wird für jedes vorhandene Attribut ein neues Element generiert, das den Namen des Attributs sowie dessen Wert übernimmt.


<Mensch>
 <xsl:for-each select="/Person/attribute::*">
  <xsl:element name="{name()}">
   <xsl:value-of select="."/>
  </xsl:element>
 </xsl:for-each>
</Mensch>

Das Ergebnis ist:


<Mensch>
   <nachname>Achim</nachname>
   <vorname>Achtlos</vorname>
   <Geburtsjahr>1970</Geburtsjahr>
</Mensch>

Namespaces im XML-Input-Dokument

Soll dasselbe Ergebnis erreicht werden, wenn der XML-Input mit einem Namespace "belastet" ist, ...


<wg:Person 
    xmlns:wg="wilfried-grupe.de" 
    wg:nachname="Zenzi" 
    wg:vorname="Zwecklos" 
    wg:Geburtsjahr="1980"/>

so bietet sich die Arbeit mit child::* und local-name() an:


<Mensch>
 <xsl:for-each 
      select="/*/child::*/attribute::*">  
  <xsl:element name="{local-name()}">
   <xsl:value-of select="."/>
  </xsl:element>
 </xsl:for-each>
</Mensch>

<Mensch>
   <nachname>Zenzi</nachname>
   <vorname>Zwecklos</vorname>
   <Geburtsjahr>1980</Geburtsjahr>
</Mensch>

Timestamp-Elemente

Ebenso ist es möglich, die Elementnamen mit einem Zeitstempel zu versehen (selten benötigt, aber doch verwendet). Für das folgende Beispiel benötige ich zwei Variablen, die die aktuelle Zeit ermitteln und zur weiteren Verwendung formatieren.


<xsl:variable name="vjetzt" 
     select="current-dateTime()"/> 
<xsl:variable name="vjetztf" 
     select="format-dateTime($vjetzt, 
        '[Y0001][M01][D1]','de','AD','DE')"/>

Diese Zeitstempel kommen nun bei der Generierung der Elementnamen zum Einsatz.


<xsl:element 
     name="element{$vjetztf}">
  <xsl:element name="wg:Tag{$vjetztf}" 
       namespace="https://www.wilfried-grupe.de">
     <xsl:value-of 
          select="day-from-dateTime($vjetzt)"/>
  </xsl:element>
  <xsl:element name="Monat{$vjetztf}">
     <xsl:value-of 
          select="month-from-dateTime($vjetzt)"/>
  </xsl:element>
  <xsl:element 
       name="Jahr{$vjetztf}" 
       namespace="https://www.wilfried-grupe.de" >
    <xsl:value-of 
         select="year-from-dateTime($vjetzt)"/>
  </xsl:element>
</xsl:element>

Interessant ist hier auch der Einsatz der XML-Schema-basierten Typkontrolle, die beim xsl:element name='Monat{$vjetztf}' sicherstellt, dass das Ergebnis eine positive Zahl sein muss.

Das Ergebnis lautet:


<element20180112>
  <wg:Tag20180112 
      xmlns:wg="https://www.wilfried-grupe.de">
      12
  </wg:Tag20180112>
  <Monat20180112>1</Monat20180112>
  <Jahr20180112
    xmlns="https://www.wilfried-grupe.de">
    2018
  </Jahr20180112>
</element20180112>

wg / 17. April 2021



Fragen? Anmerkungen? Tipps?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.



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

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/XSL_element.html