2010-01-26 6 views
5

Ai-je raison de penser qu'une déclaration apply-templates doit correspondre tous les modèles qui pourraient éventuellement être appliqués pour une sélection?Comprendre `apply-templates` correspondant

Par exemple, étant donné le fragment XML suivant:

<doc> 
    <foo bar="1" baz="2">boz</foo> 
</doc> 

et la feuille de style suivante:

<xsl:template match="/"> 
    <xsl:apply-templates select="foo" mode="xyz" /> 
</xsl:template> 

<xsl:template mode="xyz" match="foo[bar='1']"> 
    abc 
</xsl:template> 

<xsl:template mode="xyz" match="foo[baz='2']"> 
    def 
</xsl:template> 

Je pense que la sortie soit:

abc 
def 

Est-ce exact ?

Répondre

6

Non, vous ne recevez pas les deux sorties, comme un seul modèle sera sélectionné. Voir this page pour les règles sur la résolution de conflit s'il y a plusieurs modèles possibles. Après avoir corrigé votre feuille de style (de la même manière que Rubens, mais avec les mêmes modes), le dernier modèle de votre fichier xslt sera généralement appliqué. La sortie sera def. En effet, les deux modèles ont la même priorité et si votre processeur xslt ne se limite pas à une erreur de la norme exige pour appliquer le dernier:

Il est une erreur si cela laisse plus d'une règle de modèle correspondant . Un processeur XSLT peut signaler l'erreur; si elle ne signale pas l'erreur, elle doit être récupérée en choisissant, parmi les règles de modèle correspondantes restantes, celle qui se trouve en dernier dans la feuille de style.

+0

+1, bonne réponse –

0

Si vous fixez ce code XSLT (vous avez des problèmes de filtre) et diffusait, vous devriez voir:

def

Pourquoi? <xsl:apply-templates /> correspondra au premier modèle qui répond à votre condition de correspondance. Si vous avez deux modèles, vous devriez différer que par l'utilisation que <xsl:apply-templates>mode attribut, ou en utilisant <xsl:template>priority attribut:

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/doc"> 
     <xsl:apply-templates select="foo" mode="2" /> 
    </xsl:template> 

    <xsl:template mode="1" match="foo[@bar='1']"> 
     abc 
    </xsl:template> 

    <xsl:template mode="2" match="foo[@baz='2']"> 
     def 
    </xsl:template> 

</xsl:stylesheet> 
4

Si vous ne voulez que vos modèles pour correspondre à les deux attributs, alors vous juste besoin de régler la match XPATH pour sélectionner les attributs et de mettre la relation à foo dans le prédicat; plutôt que d'avoir deux modèles en conflit correspondant à l'fooélément avec la même spécificité (qui ont la même priorité).

<?xml version="1.0" encoding="UTF-8"?> 
    <xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/> 

<xsl:template match="/"> 
    <xsl:apply-templates select="doc/foo" /> 
</xsl:template> 

<!--When templates match on foo, apply templates for it's attributes --> 
<xsl:template match="foo"> 
    <xsl:apply-templates select="@*"/> 
</xsl:template> 

<!--Unique template match for the bar attribute --> 
<xsl:template match="@bar[parent::foo and .='1']"> 
    abc 
</xsl:template> 

<!--Unique template match for the baz attribute --> 
<xsl:template match="@baz[parent::foo and .='2']"> 
    def 
</xsl:template> 

</xsl:stylesheet> 
+0

Merci, c'est ce que je voulais faire. Malheureusement, je ne peux pas accepter la réponse car elle ne va pas dans le "pourquoi". ;) –