Como faço para aplicar modelos a cada nó selecionado em um for-each?
-
06-07-2019 - |
Pergunta
Eu sei que eu estou faltando alguma coisa aqui. Na transformação XSLT a seguir, o resultado real não corresponde ao resultado desejado.
Dentro do for-each
, quero aplicar o modelo match="track"
a cada elemento track
selecionado. Se eu entendi XSLT corretamente, com a configuração atual apenas nós filho de cada elemento track
selecionado são comparados com modelos, não os próprios elementos track
.
Como posso fazer os elementos track
percorrer o modelo como desejar? Eu preciso repensar toda a minha abordagem?
Nota: A transformação é executado usando PHP. declarações XML foram omitidos por brevidade.
documento XML:
<album>
<title>Grave Dancers Union</title>
<track id="shove">Somebody To Shove</track>
<track id="gold">Black Gold</track>
<track id="train">Runaway Train</track>
<producer>Michael Beinhorn</producer>
</album>
folha de estilo XSL:
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/album">
<ol>
<xsl:for-each select="track">
<li><xsl:apply-templates/></li>
</xsl:for-each>
</ol>
</xsl:template>
<xsl:template match="track">
<a href="{@id}"><xsl:apply-templates/></a>
</xsl:template>
</xsl:stylesheet>
Resultado:
<ol>
<li>Somebody To Shove</li>
<li>Black Gold</li>
<li>Runaway Train</li>
</ol>
Resultado pretendido:
<ol>
<li><a href="shove">Somebody To Shove</a></li>
<li><a href="gold">Black Gold</a></li>
<li><a href="train">Runaway Train</a></li>
</ol>
Solução
Eu concordo com 'ndim' que você provavelmente deve reestruturar seu XSLT para acabar com o xsl:. Para-cada loop
Como alternativa, você pode alterar o xsl: apply-templates para selecionar o nó faixa atual dentro do xsl: for-each
<xsl:for-each select="track">
<li>
<xsl:apply-templates select="." />
</li>
</xsl:for-each>
Mantendo o xsl:. For-each seria, pelo menos, permitir que você classifique as faixas em outra ordem, se desejado
Outras dicas
Eu tinha reestruturar-lo um pouco (se você não precisa a classificar a abordagem for-each
torna possível):
<xsl:template match="/album">
<ol>
<xsl:apply-templates select="track"/>
</ol>
</xsl:template>
<xsl:template match="track">
<li><a href="{@id}"><xsl:apply-templates/></a></li>
<xsl:template>
Isso parece mais curto e mais direto ao ponto, IMHO.
Eu acho que a sua
<xsl:for-each select="track">
<li><xsl:apply-templates/></li>
</xsl:for-each>
caminha por todos os elementos de pista com a for-each
, e, em seguida, aplica-se as regras padrão para seus descendentes. Assim, o conteúdo do for-each
possui o mesmo nó de contexto como o modelo match="track"
possui, e, portanto, o modelo match="track"
não corresponde. |
Se você realmente quiser usar o for-each
dessa maneira, você vai precisar alterar qualquer uma das duas coisas seguintes na sua abordagem:
- Adicionar um atributo
name="track"
ao modelomatch="track"
, e depois usar<xsl:call-template/>
de dentro dofor-each
(minha idéia, e pior do queTim C
de) - A solução de Uso
Tim C
usando<xsl:apply-templates select="."/>
. Isto tem a vantagem de evitar nomeação e mantendo a possibilidade de ordenar as faixas.
Acho que usando apply-modelos e modos de modelo é a solução mais limpa:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="/">
<body>
<xsl:apply-templates select="album" mode="ol" />
</body>
</xsl:template>
<xsl:template match="album" mode="ol">
<ol>
<xsl:apply-templates select="track" mode="li" />
</ol>
</xsl:template>
<xsl:template match="track" mode="li">
<li>
<xsl:apply-templates select="." />
</li>
</xsl:template>
<xsl:template match="track">
<a href="{@id}">
<xsl:value-of select="." />
</a>
</xsl:template>
</xsl:stylesheet>
resulta em:
<body>
<ol>
<li>
<a href="shove">Somebody To Shove</a>
</li>
<li>
<a href="gold">Black Gold</a>
</li>
<li>
<a href="train">Runaway Train</a>
</li>
</ol>
</body>
A for-each instrução altera o nó contexto de álbum para acompanhar. A chamada apply-templates por padrão se aplica modelos para os nós filhos do nó de contexto que no seu caso são os nós filhos do elemento de pista. Daí o seu modelo que combina 'faixa' nunca é atingido.