XSLT e XPath sintaxe> como fazer referência a um elemento em um escopo 'exterior'
Pergunta
Eu tenho o seguinte a trabalhar 100% corretamente. No entanto, para satisfazer a minha curiosidade ... há uma maneira de conseguir o mesmo sem declarar a variável currentID? Existe alguma maneira para referenciá-lo a partir de dentro a condição XPath "teste"?
A consulta XPath na condição deve se referir a 2 atributos @ ID para ver se eles combinam.
- o 'atual' @ id
- cada 'ancestral' @ id
Aqui está o código:
<xsl:variable name="currentID" select="@id" />
<xsl:attribute name="class">
<xsl:if test="count($currentPage/ancestor::node [@id = $currentID])>0">descendant-selected </xsl:if>
</xsl:attribute>
Solução
Uma vez que você selecionar o $currentID
a partir do nó de contexto:
<xsl:variable name="currentID" select="@id" />
Você pode usar a função current()
, que sempre se refere ao nó de contexto XSLT:
<xsl:attribute name="class">
<xsl:if test="count($currentPage/ancestor::node[@id = current()/@id) > 0]">
<xsl:text>descendant-selected </xsl:text>
</xsl:if>
</xsl:attribute>
Desta forma, você não precisa de uma variável.
Algumas outras notas:
- Eu recomendo usar
<xsl:text>
como mostrado acima. Isto dá-lhe mais liberdade para formatar o seu código e evitar linhas excessivamente longas. - Você não precisa fazer um
count() > 0
, simplesmente selecionando os nós é suficiente. Se não existir nenhum, o vazio nó-conjunto é devolvido. É sempre avaliada como falsa, enquanto não vazios conjuntos de nós sempre avaliar como true.
Se você se refere a nós por @id
regularmente em sua folha de estilo XSL, um <xsl:key>
seria benéfico:
<xsl:key name="kNodeById" match="node" use="@id" />
<!-- ... -->
<xsl:attribute name="class">
<xsl:if test="key('kNodeById', @id)">
<xsl:text>descendant-selected </xsl:text>
</xsl:if>
</xsl:attribute>
O current()
acima não precisa desde fora de um predicado XPath, o contexto é inalterada. Além disso, eu não count()
os nós, uma vez que este é redundante (conforme explicado).
Outras dicas
Use current () para se referir ao nó atual processado pelo template:
<xsl:if test="count($currentPage/ancestor::node [@id = current()/@id])>0">
Tim me fez pensar .... Eu acho que eu estava sobre complicar as coisas, e eu tentei o seguinte que funciona.
<xsl:if test="@id = $currentPage/ancestor::node/@id">descendant-selected </xsl:if>
XSLT parece feliz comparando um atributo com uma seleção de atributos, e avaliar verdadeiro se qualquer um deles combinar? se alguém tem uma melhor explicação de por que isso funciona ou algo melhor (mais sucinto), em seguida, colocá-lo para baixo.
Como já ficou claro, referindo-se ao "escopo externo" não era um problema, desde que você poderia fazer uma comparação direta usando o operador "=". No entanto, existem alguns casos onde você fazer necessidade atual () e mais além, onde até mesmo atual () não cortá-lo (porque você precisa para "juntar-se" entre mais do que apenas dois contextos). Nesses casos, XPath 2.0 "para" expressões são indispensáveis.
Você poderia simplesmente fazer:
<xsl:if test="count($currentPage[ancestor::node/@id = @id])>0">descendant-selected </xsl:if>