André Laugks: variable Anzahl von Kindelementen ausgeben

Hallo!

Ich habe ein XML-Dokument(Beispiel) mit folgenden Aufbau. Das Element "telefon" kann eine beliebige Anzahl an Kindelemente z.B. "nr" haben.

Ich möchte alle Elemente "nr" ausgeben.

// XML-dokument
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="test.xsl" type="text/xsl"?>
<adressbuch>
 <adresse>
  <name>Sven</name>
  <telefon>
   <nr>S. 1</nr>
   <nr>S. 2</nr>
   <modil>s. M. 1.</modil>
  </telefon>
 </adresse>
 <adresse>
  <name>Tom</name>
  <telefon>
   <nr>T. 1</nr>
   <nr>T. 2</nr>
   <nr>T. 3</nr>
   <mobil>T. M. 1.</mobil>
  </telefon>
 </adresse>
</adressbuch>

// Ausschnitt aus XSL-Template, das gesamte am Ende

Wenn ich diese Definition verwende, werden mir alle "nr" Elemente plus das "mobil" Element ausgegeben.

<xsl:template match="telefon/nr">
  <xsl:value-of select="."/><br/>
</xsl:template>

Mit folgender Definition bekomme ich nur das erste "nr" Element ausgegeben.

<xsl:template match="telefon">
  <xsl:value-of select="nr"/><br/>
</xsl:template>

Verwende ich eine Schleife, bekomme ich alle "nr" Elemente ausgegeben.

<xsl:template match="telefon">
   <xsl:for-each select="nr">
 <xsl:value-of select="."/><br/>
   </xsl:for-each>
</xsl:template>

Mhhhhh, wo habe ich ein Verstandnisproblem? Das mit der Schleife ist mir klar. Bei den anderen beiden Definitionen komme ich aber nicht ganz mit.

MfG, André Laugks
L-Andre @ gmx.de

-----------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="html" indent="yes"/>

<xsl:template match="/adressbuch">
  <html>
   <body>
    <table border="1">
     xsl:apply-templates/
    </table>
   </body>
  </html>
 </xsl:template>

<xsl:template match="adresse">
  <tr>
   <td><xsl:apply-templates select="name"/></td>
   <td><xsl:apply-templates select="telefon"/></td>
  </tr>
 </xsl:template>

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

<xsl:template match="telefon/nr">
  <xsl:value-of select="."/><br/>
 </xsl:template>

</xsl:stylesheet>

  1. Hallo André,

    Ich habe ein XML-Dokument(Beispiel) mit folgenden Aufbau. Das Element "telefon" kann eine beliebige Anzahl an Kindelemente z.B. "nr" haben.

    Ich möchte alle Elemente "nr" ausgeben.

    // XML-dokument
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet href="test.xsl" type="text/xsl"?>
    <adressbuch>
    <adresse>
      <name>Sven</name>
      <telefon>
       <nr>S. 1</nr>
       <nr>S. 2</nr>
       <modil>s. M. 1.</modil>
      </telefon>
    </adresse>
    <adresse>
      <name>Tom</name>
      <telefon>
       <nr>T. 1</nr>
       <nr>T. 2</nr>
       <nr>T. 3</nr>
       <mobil>T. M. 1.</mobil>
      </telefon>
    </adresse>
    </adressbuch>

    // Ausschnitt aus XSL-Template, das gesamte am Ende

    Wenn ich diese Definition verwende, werden mir alle "nr" Elemente plus das "mobil" Element ausgegeben.

    <xsl:template match="telefon/nr">
      <xsl:value-of select="."/><br/>
    </xsl:template>

    Ja, weil Du "oben" (im Template für die <adresse>-Elemente) mit <xsl:apply-templates select="telefon"> eine Template Rule für die <telefon>-Elemente aufrufst. Die gibt es aber in diesem Fall nicht (da das match-Attribut den Wert telefon/nr) hat. Da der XSL-Prozessor also keine Template Rule findet, wendet er für den selektierten Knoten eine eingebaute Template Rule an (so die Regel). Für Knoten vom Typ "Element" lautet diese Regel, nehme dir alle Kinder des selektierten Knotens vor und prozessiere sie (suche Template Rules dafür). Das ist äquivalent zum Aufruf von xsl:apply-templates. Kinder von <telefon> sind die <nr>-Elemente und <nr>-Elemente. Auch für diese findet der Prozessor keine Template Rules. Also ruft er erneut die eingebaute Template Rule für die jeweiligen Elementknoten auf. Die Kinder der Knoten werden daher wieder prozessiert (Template Rules dafür gesucht). Bei den Kindern handelt es sich um Textknoten, auch für diese gibt es keine Template Rules in deinem Style Sheet. Folge: er wendet die eingebaute Template Rule für Textknoten an, die da lautet: Geben den Zeichenkettenwert des Textknoten aus. Und voilà so tauchen dann die Werte in deiner Tabelle auf.

    Mit folgender Definition bekomme ich nur das erste "nr" Element ausgegeben.

    <xsl:template match="telefon">
      <xsl:value-of select="nr"/><br/>
    </xsl:template>

    Ja das funktioniert nicht, weil du mit <xsl:value-of select="nr"> nicht nur einen Knoten auswählst, um dann dessen Zeichenkettenwert in das Ergebnsidokument zu schreiben, sondern eine Knotenmenge. Und die Regel in XSLT lautet dann eben, für diesen Fall nur den ersten Zeichenkettenwert des ersten Knotens in der Knotenmenge auszugeben.

    Aber auch dass ist nicht das, was du möchtest. Hier hast du zwar nun eine Template Rule für die <telefon>-Elemente, aber die willst du ja auch nicht. Eigentlich benötigst du eine für die <nr>-Elemente, die dann für *alle* <nr>-Elemente gilt.

    Dazu musst du einfach "oben" <xsl:apply-templates select="telefon"> in <xsl:apply-templates select="telefon/nr"> ändern und statt der Template Rule für die <telefon>-Elemente eine für die <nr>-Elemente schreiben:

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

    Verwende ich eine Schleife, bekomme ich alle "nr" Elemente ausgegeben.

    <xsl:template match="telefon">
       <xsl:for-each select="nr">
    <xsl:value-of select="."/><br/>
       </xsl:for-each>
    </xsl:template>

    Ja, dass ist logisch wie du selber sagst.

    Mhhhhh, wo habe ich ein Verstandnisproblem? Das mit der Schleife ist mir klar. Bei den anderen beiden Definitionen komme ich aber nicht ganz mit.

    Uff, hoffe du hast verstanden. Da schreibt man sich ja die Finger wund, um das Zeug halbwegs plastisch zu erklären....

    Gruß
    Franz

    1. Hallo!

      Danke für Deine Antwort! Deine antworten leuchten mir ein.

      Leider kann ich es nicht ausprobieren, da ich heute für mein Monitor(Schalter defekt) ein Ersatzmonitor bekommen habe. Leider kann man bei dem Ersatzmonitor die Schärfe nicht richtig einstellen. Ich bekomme morgen ein Ersatzersatzmonitor ;-).

      Das nervt so, naja..., so hat mal Zeit für andere Dinge.

      MfG, André Laugks
      L-Andre @ gmx.de

  2. Servus

    // XML-dokument
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet href="test.xsl" type="text/xsl"?>
    <adressbuch>
    <adresse>
      <name>Sven</name>
      <telefon>
       <nr>S. 1</nr>
       <nr>S. 2</nr>
       <modil>s. M. 1.</modil>
      </telefon>
    </adresse>
    <adresse>
      <name>Tom</name>
      <telefon>
       <nr>T. 1</nr>
       <nr>T. 2</nr>
       <nr>T. 3</nr>
       <mobil>T. M. 1.</mobil>
      </telefon>
    </adresse>
    </adressbuch>

    Hier noch ein Beispiel wie man es machen könnte.
    Es gibt grundsätzlich die Push und die Pop Methodik,
    wobei dein letztes Beispiel beide nutzt.

    Hier nun reine Pull-Algorithmen (wie deine ersten beiden Beispiele):

    So könntest Du auch kompletten Zugriff auf all Deine XML Elemente in deinen XML-Dateien bekommen:

    <!-- er matcht hier das Wurzelelement -->
    <xsl:template match="adressbuch">
      Mein Adressbuch:
      xsl:apply-templates/
    </xsl:template>

    <!-- falls er auch das adresse Tag stösst springt er hierhinein -->
    <xsl:template match="adresse">
      xsl:apply-templates/
    </xsl:template>

    <!-- falls er auch das telefon Tag stösst springt er hierhinein -->
    <xsl:template match="telefon">
      xsl:apply-templates/
    </xsl:template>

    <!-- falls er auch das nr Tag stösst springt er hierhinein -->
    <xsl:template match="nr">
      Telefonnummer:
      xsl:apply-templates/
    </xsl:template>

    <!-- falls er auch das mobil Tag stösst springt er hierhinein -->
    <xsl:template match="mobil">
      Mobil-Telefonnummer:
      xsl:apply-templates/
    </xsl:template>

    ciao
    -Marco Wagner-

    1. hallo,

      Es gibt grundsätzlich die Push und die Pop Methodik,

      push und pull!

      Hier nun reine Pull-Algorithmen

      wie du es ja richtig sagst ;-)
      wohl ein vertippser

      grüße
      Thomas

      1. hallo,

        Es gibt grundsätzlich die Push und die Pop Methodik,

        push und pull!

        Arg, Danke für den Hinweis.

        Natürlich Pull wie "Ziehen".
        Man wird in die Templates hineingezogen,
        je nach Regel.

        Hier nun reine Pull-Algorithmen

        wie du es ja richtig sagst ;-)
        wohl ein vertippser

        grüße
        Thomas