Penghitung di dalam xsl: untuk setiap loop

90

Cara mendapatkan penghitung di dalam xsl: for-each loop yang akan mencerminkan jumlah elemen saat ini yang diproses.
Misalnya XML sumber saya

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

Yang ingin saya dapatkan adalah:

<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>

XSLT yang akan dimodifikasi:

<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>

Jadi pertanyaannya adalah apa yang harus menggantikan ???. Apakah ada kata kunci standar atau apakah saya hanya harus mendeklarasikan variabel dan menambahkannya di dalam loop?

Karena pertanyaannya cukup panjang, saya mungkin mengharapkan satu baris atau satu kata jawaban :)

kristof
sumber

Jawaban:

142

position(). MISALNYA:

<countNo><xsl:value-of select="position()" /></countNo>
kotak merah
sumber
9
Ini semua bagus dan keren sampai Anda harus menambahkan filter seperti xsl: jika di dalam xsl Anda: untuk masing-masing. Maka posisi () TIDAK BERGUNA dan Anda membutuhkan penghitung yang tepat.
Mike Starov
4
@ Mike Stavrov Itu bukan bagian dari pertanyaan! Tidak dapat mencakup semua situasi
redsquare
@redquare Benar. Hanya menambahkan dua sen saya. Saya harus menulis fungsi ekstensi XSL untuk menyelesaikan situasi yang saya gambarkan. Mungkin saya harus bertanya kepada orang-orang di sini tentang solusi yang lebih baik.
Mike Starov
2
@MikeStarov lalu bagaimana melakukannya jika ada xsl:ifdi dalam xsl:for-each? Apa itu "counter yang tepat"? Bisakah Anda menunjukkan beberapa sumber?
lajarre
@lajarre Anda menulis fungsi ekstensi kustom untuk dipanggil dari XSL. Anda juga dapat melakukan pemrosesan dua lintasan. Proses sekali dan simpan ke xsl: variable. Kemudian terapkan templat pada konten variabel xsl dan tambahkan penomoran menggunakan posisi ()
Mike Starov
13

Coba masukkan <xsl:number format="1. "/><xsl:value-of select="."/><xsl:text> sebagai ganti ???.

Perhatikan "1." - ini adalah format angka. Info lebih lanjut: di sini

m_pGladiator
sumber
Terima kasih, itu bacaan yang menarik juga. Saya mungkin akan menggunakan pendekatan itu ketika beberapa pemformatan diperlukan
kristof
Versi XSLT 1.0:<xsl:number format="1. " value="position()"/>
jsuddsjr
10

Mencoba:

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

Edit - mengalami pembekuan otak di sana, posisi () lebih mudah!

Luke Bennett
sumber
3
Masih bisa berguna, terutama jika Anda memilih berdasarkan kriteria selain posisi (). +1
jsuddsjr
7

Anda juga bisa menjalankan pernyataan bersyarat di Postion () yang bisa sangat membantu dalam banyak skenario.

untuk mis.

 <xsl:if test="(position( )) = 1">
     //Show header only once
    </xsl:if>
Arun Arangil
sumber
2
Ini gagal jika Anda memiliki filter seperti xsl: sort karena item pertama mungkin bukan yang pertama diproses.
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
sumber