2010-11-15 4 views
4

je le xsl stylesheet suivant:Compte le nombre d'éléments retournés par <call-template>

<xsl:stylesheet xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" encoding="utf-8"/> 

    <xsl:template match="/"> 
    <xsl:variable name="elements"> 
     <xsl:call-template name="get-some-nodes"/> 
    </xsl:variable> 

    <root> 
     <values> 
     <xsl:copy-of select="$elements"/> 
     </values> 
     <count> 
     <xsl:value-of select="count($elements)"/> 
     </count> 
    </root> 
    </xsl:template> 

    <xsl:template name="get-some-nodes"> 
    <node>1</node> 
    <node>2</node> 
    <node>3</node> 
    </xsl:template> 

</xsl:stylesheet> 

(Il ne devrait pas importer ce que xml vous l'appliquez à, il génère ses propres données).

Le résultat de cette de cette (en utilisant xsltproc) est:

<?xml version="1.0" encoding="utf-8"?> 
<root xmlns="http://www.w3.org/1999/xhtml" xmlns:set="http://exslt.org/sets"> 
    <values> 
    <node>1</node> 
    <node>2</node> 
    <node>3</node> 
    </values> 
    <count>1</count> 
</root> 

Étant donné que le modèle appelé renvoie trois noeuds, je me attendais « count (éléments $) » pour être 3, mais il est un. Je soupçonnais peut-être que les résultats étaient enveloppés dans une sorte de nœud racine, mais toute tentative de faire count ($ elements/*) ou similaire échouait, car $ elements est un fragment d'arbre de résultat, et non un ensemble de nœuds.

Je n'ai pas accès à l'un des goodies de exslt ou xslt2.0, il existe sûrement un moyen d'obtenir le nombre de nœuds stockés dans une variable?

Je serais également heureux de compter les nœuds renvoyés par le modèle d'appel sans utiliser de variable intermédiaire, mais je ne vois pas comment cela serait possible.

+0

Bonne question, +1. Voir ma réponse pour une explication détaillée et des solutions. –

Répondre

2
<xsl:variable name="elements"> 
    <xsl:call-template name="get-some-nodes"/> 
</xsl:variable> 

<root> 
    <values> 
    <xsl:copy-of select="$elements"/> 
    </values> 
    <count> 
    <xsl:value-of select="count($elements)"/> 
    </count> 
</root> 

Dans XSLT 1.0, chaque fois que les noeuds sont copiés dans le corps d'un <xsl:variable>, le contenu de cette variable est une RTF (les résultats Tree_fragment) et doit être converti en un arbre régulier avant de poursuivre le traitement avec XPath.

Un RTF peut être converti en un arbre normal en utilisant uniquement une fonction d'extension, habituellement appelée xxx:node-set(), où le préfixe xxx est lié à un espace de noms spécifique au fournisseur.

Pour obtenir le nombre d'éléments qui sont au plus haut niveau de cet arbre, vous avez besoin:

count(xxx:node-set($elements)/*) 

Voici quelques espaces de noms, auxquels xxx: est souvent lié:

"http://exslt.org/common/" 

"urn:schemas-microsoft-com:xslt" 

Dans XSLT 2.0 le "type" RTF n'existe plus et vous pouvez simplement avoir:

count($elements/*) 

si le type de $elements n'est pas spécifié (la valeur par défaut est document-node())

ou

count($elements) 

si le type de $elements est spécifié comme element()*

+0

Bonne réponse, mais je ne pense pas avoir une fonction de jeu de nœuds à ma disposition. Je prévois finalement de déployer cette page en tant que confluence (produit wiki d'atlassian), et après l'expérimentation, elle ne semble supporter aucune de ces extensions. Je cherche une solution XSLT 1 vanille, malheureusement. – gfxmonk

+0

@gfxmonk: Il est très probable que votre processeur XSLT * possède * une fonction 'xxx: node-set()' - la plupart des processeurs XSLT ont. Quel est le processeur XSLT que vous utilisez?Si vous ne savez pas, obtenez le résultat de cette fonction: 'system-property (xsl: vendor)' ou 'system-property (xsl: vendor-url)'. –

+0

Ahh c'est un bon truc à savoir. J'utilise apache xalan-j. Cependant, j'ai l'intention d'exécuter ceci avec plusieurs processeurs xslt (xalan et libxslt), donc je préférerais toujours une solution sans utiliser de telles extensions. – gfxmonk

Questions connexes