Home
Über mich
Veröffentlichungen

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

XSL-T / Die XSLT - Struktur / xsl:apply-templates, xsl:next-match / xsl:apply-templates: Teilkonvertierung

xsl:apply-templates: Teilkonvertierung

xsl:apply-templates: Teilkonvertierung

➪ Manchmal stehen Sie vor der Aufgabe, ein komplexes XML-Input-Dokument fast unverändert übernehmen und nur eine Teilstruktur verändern zu müssen.

Auf dieser Seite:

Siehe xsl:apply-templates in XSLT 1.0, xsl:apply-templates in XSLT 2.0 und xsl:apply-templates in XSLT 3.0.

Nehmen Sie an, in dem folgenden XML-Dokument sollen die Kauf-Elemente von der Element- in die Attributschreibweise überführt und mit einem neuen Namespace versehen werden. Auch das ROOT-Element ist entsprechend anzupassen.


<ROOT>
  <Ort>
   <id>1</id>
   <name>Neustadt</name>
  </Ort>
  <Mensch>
   <id>1</id>
   <name>Holzflos</name>
   <vorname>Hugo</vorname>
   <Gehalt>234.56</Gehalt>
   <idOrt>1</idOrt>
  </Mensch>
  <Kauf>
   <id>1</id>
   <anzahl>3</anzahl>
   <idMensch>1</idMensch>
   <idWare>1</idWare>
  </Kauf>
  <Kauf>
   <id>1</id>
   <anzahl>6</anzahl>
   <idMensch>1</idMensch>
   <idWare>1</idWare>
  </Kauf>
  <Ware>
   <id>1</id>
   <bez>Hemd</bez>
   <preis>12.99</preis>
  </Ware>
</ROOT>

Lösung über <xsl:template match="*"> und <xsl:apply-templates/>

Die einfachste Version ist die Arbeit über <xsl:template match="*"> und <xsl:apply-templates/>. Durch einen rekursiven Aufruf durchlaufen sie einen ganzen XML-Baum; spezielle xsl:template's und Fallunterscheidungen übernehmen die Sonderbehandlungen.


<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:z="www.wilfried-grupe.de" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="*">       
        <xsl:variable name="vename" >
            <xsl:choose>
                <xsl:when test="name() = 'ROOT'">z:NEUESROOT</xsl:when>                
                <xsl:otherwise>
                    <xsl:value-of select="name()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>        
        <xsl:element name="{$vename}">
            <xsl:for-each select="attribute::*">
                <xsl:attribute name="{name()}">
                    <xsl:value-of select="."/>
                </xsl:attribute>
            </xsl:for-each>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="Kauf">
        <z:k>
            <xsl:for-each select="child::*">
                <xsl:attribute name="{local-name()}" select="."/>
            </xsl:for-each>
        </z:k>
    </xsl:template>
</xsl:stylesheet>

Alternative Lösung

Die Umsetzung ist alternativ in der Form möglich, dass eine xsl:for-each-Schleife sämtliche Childnodes des Root-Elements durchläuft und via xsl:apply-templates jeweils ein passendes Template aufruft.


<xsl:stylesheet version="2.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:z="www.wilfried-grupe.de">
  <xsl:output method="xml" 
       version="1.0" 
       encoding="UTF-8" 
       indent="yes"/>
  <xsl:template match="/">
    <z:NEUESROOT>
      <xsl:for-each select="/ROOT/child::*">
        <xsl:apply-templates select="."/>
      </xsl:for-each>
    </z:NEUESROOT>
  </xsl:template>

Das <xsl:template match="Kauf"/> übernimmt die gewünschten Änderungen:


  <xsl:template match="Kauf">
    <z:k>
      <xsl:for-each select="child::*">
        <xsl:attribute name="{local-name()}" select="."/>
      </xsl:for-each>
    </z:k>
  </xsl:template>

Die restlichen Childnodes des ursprünglichen XML-Input-ROOT-Nodes werden über ein allgemeines Template, das alle weiteren Elemente anspricht, übernommen. Gegebenenfalls wäre eine Implementierung auch über xsl:copy-of oder ein weiteres xsl:apply-templates sinnvoll.


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

Das Ergebnis ist jedenfalls vorerst nach Wunsch:


<z:NEUESROOT xmlns:z="www.wilfried-grupe.de">
  <Ort>
    <id>1</id>
    <name>Neustadt</name>
  </Ort>
  <Mensch>
    <id>1</id>
    <name>Holzflos</name>
    <vorname>Hugo</vorname>
    <Gehalt>234.56</Gehalt>
    <idOrt>1</idOrt>
  </Mensch>
  <z:k id="1" anzahl="3" idMensch="1" idWare="1"/>
  <z:k id="1" anzahl="6" idMensch="1" idWare="1"/>
  <Ware>
    <id>1</id>
    <bez>Hemd</bez>
    <preis>12.99</preis>
  </Ware>
</z:NEUESROOT>

wg / 27. Juni 2020



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/applytemplates_neue_Teilstruktur.html