Contador dentro de xsl: for-each loop


89

Como obter um contador dentro de xsl: for-each loop que refletiria o número do elemento atual processado.
Por exemplo, meu XML de origem é

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

O que eu quero é:

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

O XSLT para modificar:

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

Portanto, a questão é o que colocar no lugar de ???. Existe alguma palavra-chave padrão ou devo simplesmente declarar uma variável e incrementá-la dentro do loop?

Como a pergunta é muito longa, provavelmente devo esperar uma resposta de uma linha ou uma palavra :)

Respostas:


141

position(). POR EXEMPLO:

<countNo><xsl:value-of select="position()" /></countNo>

9
Isso está tudo bem e elegante até que você tenha que adicionar um filtro como xsl: if dentro de seu xsl: for-each. Então a posição () é INÚTIL e você precisa do contador adequado.
Mike Starov

4
@Mike Stavrov Isso não fazia parte da questão! Não é possível cobrir todas as situações
redsquare

@redsquare correto. Apenas adicionando meus dois centavos. Tive que escrever uma função de extensão XSL para resolver minha situação descrita. Talvez eu devesse perguntar às pessoas aqui sobre soluções melhores.
Mike Starov

2
@MikeStarov então como fazer se houver um xsl:ifdentro do xsl:for-each? O que é um "contador adequado"? Você pode apontar para algum recurso?
lajarre

@lajarre Você escreve uma função de extensão customizada para ser chamada a partir do XSL. Você também pode fazer o processamento de duas passagens. Processe uma vez e salve em xsl: variable. Em seguida, aplique modelos em conteúdos de variáveis ​​xsl e adicione numeração usando position ()
Mike Starov

13

Tente inserir <xsl:number format="1. "/><xsl:value-of select="."/><xsl:text> no lugar de ???.

Observe o "1" - este é o formato de número. Mais informações: aqui


Obrigado, essa também é uma leitura interessante. Provavelmente usarei essa abordagem quando alguma formatação for necessária
Kristof

Versão XSLT 1.0:<xsl:number format="1. " value="position()"/>
jsuddsjr

10

Experimentar:

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

Editar - teve um congelamento do cérebro, position () é mais simples!


3
Ainda pode ser útil, especialmente se você estiver selecionando com base em critérios diferentes de position (). +1
jsuddsjr

7

Você também pode executar instruções condicionais no Postion (), o que pode ser realmente útil em muitos cenários.

por exemplo.

 <xsl:if test="(position( )) = 1">
     //Show header only once
    </xsl:if>

2
Isso falhará se você tiver um filtro como xsl: sort porque o primeiro item pode não ser o primeiro a ser processado.
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>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.