(aktualisiert!)

IT-Trainings in Zeiten des Corona-Virus, Veranstaltungstipps der www.gfu.net:
Schulung XML Einfuehrung und Grundlagen *** Schulung Python fuer Programmiereinsteiger *** Schulung XML, XSLT, XPath, XSL-FO Einfuehrung *** Schulung Java/JSP/HTML/JDBC/XML Komplett *** Schulung XML mit Altova XMLSpy *** Schulung XML Grundlagen, XSL-FO, SVG, DocBook, DITA *** Schulung XML - der professionelle Ueberblick *** Schulung XML-Schema Intensiv *** Schulung Einstieg in die Programmierung *** Schulung C++ fuer Programmiereinsteiger *** Schulung VB.NET fuer Visual Basic-Programmierer ***


XPath 3.0, XPath 2.0, XPath 1.0 / XPath-Achsen / preceding::*

preceding::*

preceding::*

➪ Mit preceding::* erhalten Sie Vorgänger-Nodes des aktuellen Knotens. Analog dem following::* erhalten Sie bei preceding::* sämtliche Nodes und deren Childnodes, die dem adressierten Node /Orte/Ort[2]/Mensch[2] vorausgehen.

Auf dieser Seite:

pic/XPath_preceding.jpg


 <xsl:template match="/">
  <ergebnis>
   <xsl:for-each 
        select="/Orte/Ort[2]/Mensch[2]/preceding::*">
    <e nr="{position()}">
     <xsl:call-template name="generateXPath"/>
    </e>
   </xsl:for-each>
  </ergebnis>
 </xsl:template>

Je nach Umfang des Gesamtdokuments und nach Adressierung des aktuellen Nodes kann der Output sehr umfangreich sein. Erfasst wird jeder vorhergehende Node mit all seinen Childnodes, unabhängig von dem jeweiligen Namen. Möchten Sie dagegen nur die vorhergehenden Nodes eines bestimmten Namens ansprechen (also z.B. Mensch), sämtliche anderen Nodes jedoch ignorieren, so lautet der Ausdruck:


<xsl:for-each 
     select="/Orte/Ort[2]/Mensch[2]/preceding::Mensch">
...
</xsl:for-each>

Dann erhalten Sie auch nur die erwähnten Nodes Mensch ohne deren Parent- oder Childnodes. Das Ergebnis erinnert an preceding-sibling::Mensch, ist aber doch anders.

pic/XPath_preceding_Mensch.png

preceding und Namespace

Weist das XML-Dokument Namespaces auf, so ist es ausreichend, den Namespace-Präfix mit einzubinden: preceding::ns3:Mensch.


<xsl:stylesheet 
    xmlns:d="www.wilfried-grupe.de/Beispiele/2018" 
    xmlns:ns1="www.wilfried-grupe.de/Orte/2018"
    xmlns:ns2="www.wilfried-grupe.de/Ort" 
    xmlns:ns3="www.wilfried-grupe.de/Mensch"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
      <ergebnis>
        <xsl:for-each 
            select="/ns1:Orte/ns2:Ort[2]
                             /ns3:Mensch[2]
                             /preceding::ns3:Mensch">
          <M>
              <xsl:value-of select="d:vorname"/>
          </M>
        </xsl:for-each>
      </ergebnis>
    </xsl:template>
</xsl:stylesheet>

Jedem XML-Element seine ID

In dem folgenden XML-Dokument soll jeder <Ort> und jeder <Mensch>, der das Element name aufweist, ein eindeutiges Attribut @ID zugewiesen werden.


<?xml version="1.0" encoding="UTF-8"?>
<Orte>  
  <Ort>
    <id>1</id>
    <name>Neustadt</name>
    <Mensch>      
      <id>eins</id>
      <name>Holzflos</name>
      <vorname>HUGO</vorname>
    </Mensch>
    <Mensch>
      <id>4</id>      
      <vorname>Nicole</vorname>
    </Mensch>
    <Mensch>
      <id>9</id>
      <name>Sprachlos</name>
      <vorname>Stefan</vorname>      
    </Mensch>
    <Mensch>
      <id>2</id>
      <name>Sagblos</name>
      <vorname>Stefan</vorname>
    </Mensch>
    <Mensch>
      <id>3</id>
      <name>Sorglos</name>
      <vorname>SIGGI</vorname>
    </Mensch>
    <Mensch>
      <id>7</id>
      <name>Herzlos</name>
      <vorname>Heini</vorname>
    </Mensch>
  </Ort>
  <Ort>
    <id>2</id>
    <name>Darmstadt</name>    
    <Mensch>
      <id>8</id>
      <name>Rhodos</name>
      <vorname>Rudi</vorname>
    </Mensch>
    <Mensch>
      <id>15</id>
      <name>Kolos</name>
      <vorname>Karl</vorname>
    </Mensch>
    <Mensch>
      <id>16</id>
      <name>SINNLOS</name>
      <vorname>Simone</vorname>
    </Mensch>
    <Mensch>
      <id>17</id>
      <name>Brotlos</name>
      <vorname>Berta</vorname>
    </Mensch>
    <Mensch>
      <id>18</id>
      <name>Wortlos</name>
      <vorname>Werner</vorname>
    </Mensch>
    <Mensch>
      <id>19</id>
      <name>Lustlos</name>
      <vorname>Ludwig</vorname>
    </Mensch>
  </Ort>
  <Ort>
    <id>3</id>
    <name>Kapstadt</name>
    <Mensch>
      <id>5</id>
      <name>Wasistlos</name>
      <vorname>Willi</vorname>
    </Mensch>
    <Mensch>
      <id>10</id>
      <name>Ruhelos</name>
      <vorname>Rita</vorname>
    </Mensch>
    <Mensch>
      <id>11</id>
      <name>Schlaflos</name>
      <vorname>Susi</vorname>
    </Mensch>
    <Mensch>
      <id>12</id>
      <name>Rielos</name>
      <vorname>Lotte</vorname>
    </Mensch>
    <Mensch>
      <id>6</id>
      <name>Bodenlos</name>
      <vorname>Betty</vorname>
    </Mensch>
    <Mensch>
      <id>13</id>
      <name>Muehelos</name>
      <vorname>Martin</vorname>
    </Mensch>
    <Mensch>
      <id>14</id>      
      <vorname>Liane</vorname>
    </Mensch>
  </Ort>
</Orte>

Diese Aufgabe können Sie via preceding mit folgendem XSL-Stylesheet lösen:


<xsl:template match="*">
  <xsl:element name="{local-name()}">
    <xsl:if test="name">
      <xsl:attribute name="ID">    
        <xsl:choose>
          <xsl:when test="name() = 'Ort'">
            <xsl:value-of 
                 select="count(preceding::Ort[name]) + 1 "/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of 
                 select="concat( count(preceding::Ort[name]) + 1, 
                 '.', 
                 count(preceding-sibling::Mensch[name]) + 1 ) "/>    
          </xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>
    </xsl:if>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>

Das Ergebnis lautet:


<?xml version="1.0" encoding="UTF-8"?>
<Orte>
  <Ort ID="1">
    <id>1</id>
    <name>Neustadt</name>
    <Mensch ID="1.1">      
      <id>eins</id>
      <name>Holzflos</name>
      <vorname>HUGO</vorname>
    </Mensch>
    <Mensch>
      <id>4</id>      
      <vorname>Nicole</vorname>
    </Mensch>
    <Mensch ID="1.2">
      <id>9</id>
      <name>Sprachlos</name>
      <vorname>Stefan</vorname>      
    </Mensch>
    <Mensch ID="1.3">
      <id>2</id>
      <name>Sagblos</name>
      <vorname>Stefan</vorname>
    </Mensch>
    <Mensch ID="1.4">
      <id>3</id>
      <name>Sorglos</name>
      <vorname>SIGGI</vorname>
    </Mensch>
    <Mensch ID="1.5">
      <id>7</id>
      <name>Herzlos</name>
      <vorname>Heini</vorname>
    </Mensch>
  </Ort>
  <Ort ID="2">
    <id>2</id>
    <name>Darmstadt</name>    
    <Mensch ID="2.1">
      <id>8</id>
      <name>Rhodos</name>
      <vorname>Rudi</vorname>
    </Mensch>
    <Mensch ID="2.2">
      <id>15</id>
      <name>Kolos</name>
      <vorname>Karl</vorname>
    </Mensch>
    <Mensch ID="2.3">
      <id>16</id>
      <name>SINNLOS</name>
      <vorname>Simone</vorname>
    </Mensch>
    <Mensch ID="2.4">
      <id>17</id>
      <name>Brotlos</name>
      <vorname>Berta</vorname>
    </Mensch>
    <Mensch ID="2.5">
      <id>18</id>
      <name>Wortlos</name>
      <vorname>Werner</vorname>
    </Mensch>
    <Mensch ID="2.6">
      <id>19</id>
      <name>Lustlos</name>
      <vorname>Ludwig</vorname>
    </Mensch>
  </Ort>
  <Ort ID="3">
    <id>3</id>
    <name>Kapstadt</name>
    <Mensch ID="3.1">
      <id>5</id>
      <name>Wasistlos</name>
      <vorname>Willi</vorname>
    </Mensch>
    <Mensch ID="3.2">
      <id>10</id>
      <name>Ruhelos</name>
      <vorname>Rita</vorname>
    </Mensch>
    <Mensch ID="3.3">
      <id>11</id>
      <name>Schlaflos</name>
      <vorname>Susi</vorname>
    </Mensch>
    <Mensch ID="3.4">
      <id>12</id>
      <name>Rielos</name>
      <vorname>Lotte</vorname>
    </Mensch>
    <Mensch ID="3.5">
      <id>6</id>
      <name>Bodenlos</name>
      <vorname>Betty</vorname>
    </Mensch>
    <Mensch ID="3.6">
      <id>13</id>
      <name>Muehelos</name>
      <vorname>Martin</vorname>
    </Mensch>
    <Mensch>
      <id>14</id>      
      <vorname>Liane</vorname>
    </Mensch>
  </Ort>
</Orte>

Tipp: Um eine andere Reihenfolge des Ergebnisses zu erhalten, versuchen Sie es mit


<xsl:choose>
  <xsl:when test="name() = 'Ort'">
    <xsl:value-of select="count(following::Ort[name]) + 1  "/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of 
         select="concat( count(following::Ort[name]) + 1, 
                 '.', 
                 count(following-sibling::Mensch[name]) + 1 )  "/>        
  </xsl:otherwise>
</xsl:choose>

... oder mit :


<xsl:number format="1" count="Ort | Mensch" level="any"/>

Siehe auch

wg / 7. Mai 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/XPath_Achsen5.html