Zähler innerhalb von xsl: für jede Schleife

89

So erhalten Sie einen Zähler in xsl: für jede Schleife, der die Anzahl der aktuell verarbeiteten Elemente widerspiegelt.
Zum Beispiel ist mein Quell-XML

<books>
    <book>
        <title>The Unbearable Lightness of Being </title>
    </book>
    <book>
        <title>Narcissus and Goldmund</title>
    </book>
    <book>
        <title>Choke</title>
    </book>
</books>

Was ich bekommen möchte ist:

<newBooks>
    <newBook>
        <countNo>1</countNo>
        <title>The Unbearable Lightness of Being </title>
    </newBook>
    <newBook>
        <countNo>2</countNo>
        <title>Narcissus and Goldmund</title>
    </newBook>
    <newBook>
        <countNo>3</countNo>
        <title>Choke</title>
    </newBook>
</newBooks>

Das zu ändernde XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <newBooks>
            <xsl:for-each select="books/book">
                <newBook>
                    <countNo>???</countNo>
                    <title>
                        <xsl:value-of select="title"/>
                    </title>
                </newBook>
            </xsl:for-each>
        </newBooks>
    </xsl:template>
</xsl:stylesheet>

Die Frage ist also, was anstelle von ???. Gibt es ein Standardschlüsselwort oder muss ich einfach eine Variable deklarieren und innerhalb der Schleife erhöhen?

Da die Frage ziemlich lang ist, sollte ich wahrscheinlich eine Zeile oder ein Wort Antwort erwarten :)

kristof
quelle

Antworten:

141

position(). Z.B:

<countNo><xsl:value-of select="position()" /></countNo>
rotes Quadrat
quelle
9
Dies ist alles in Ordnung und gut, bis Sie einen Filter wie xsl hinzufügen müssen: wenn in Ihrem xsl: für jeden. Dann ist position () USELESS und Sie benötigen einen geeigneten Zähler.
Mike Starov
4
@ Mike Stavrov Das war nicht Teil der Frage! Kann nicht jede Situation
abdecken
@redsquare Richtig. Ich füge nur meine zwei Cent hinzu. Ich musste eine XSL-Erweiterungsfunktion schreiben, um meine beschriebene Situation zu lösen. Vielleicht sollte ich die Leute hier nach besseren Lösungen fragen.
Mike Starov
2
@ MikeStarov wie geht es dann, wenn es eine xsl:ifin der gibt xsl:for-each? Was ist ein "richtiger Zähler"? Können Sie auf eine Ressource verweisen?
Lajarre
@lajarre Sie schreiben eine benutzerdefinierte Erweiterungsfunktion, die von XSL aufgerufen werden soll. Sie können auch zwei Durchgänge verarbeiten. Einmal verarbeiten und in xsl: variable speichern. Wenden Sie dann Vorlagen auf den Inhalt von xsl-Variablen an und fügen Sie die Nummerierung mit position () hinzu
Mike Starov
13

Versuchen Sie, <xsl:number format="1. "/><xsl:value-of select="."/><xsl:text>anstelle von ??? einzufügen.

Beachten Sie die "1." - dies ist das Zahlenformat. Mehr Infos: hier

m_pGladiator
quelle
Danke, das ist auch eine interessante Lektüre. Ich werde diesen Ansatz wahrscheinlich verwenden, wenn eine Formatierung erforderlich ist
kristof
XSLT 1.0 Version:<xsl:number format="1. " value="position()"/>
jsuddsjr
10

Versuchen:

<xsl:value-of select="count(preceding-sibling::*) + 1" />

Bearbeiten - hatte dort ein Einfrieren des Gehirns, position () ist einfacher!

Luke Bennett
quelle
3
Dies kann dennoch nützlich sein, insbesondere wenn Sie anhand anderer Kriterien als position () auswählen. +1
jsuddsjr
7

Sie können auch bedingte Anweisungen für Postion () ausführen, was in vielen Szenarien sehr hilfreich sein kann.

für zB.

 <xsl:if test="(position( )) = 1">
     //Show header only once
    </xsl:if>
Arun Arangil
quelle
2
Dies schlägt fehl, wenn Sie einen Filter wie xsl: sort haben, da dann möglicherweise nicht das erste Element verarbeitet wird.
Alexis Wilke
5
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <newBooks>
                <xsl:for-each select="books/book">
                        <newBook>
                                <countNo><xsl:value-of select="position()"/></countNo>
                                <title>
                                        <xsl:value-of select="title"/>
                                </title>
                        </newBook>
                </xsl:for-each>
        </newBooks>
    </xsl:template>
</xsl:stylesheet>
Santiago Cepas
quelle