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