2010-01-26 19 views
5

Sono corretto nel ritenere che una dichiarazione apply-templates debba corrispondere a tutti i modelli che potrebbero essere applicati per una selezione?Comprensione corrispondenza 'apply-templates`

Ad esempio, dato il seguente frammento XML:

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

e il seguente foglio di stile:

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

mi aspetterei l'uscita di essere:

abc 
def 

È questo corretto ?

risposta

6

No, non si ottiene entrambe le uscite, come sarà selezionato un solo modello. Vedere this page per le regole sulla risoluzione dei conflitti se esistono più modelli possibili.

Dopo aver corretto il foglio di stile (in modo simile a come lo ha fatto Rubens, ma con le stesse modalità), questo di solito comporterà l'applicazione dell'ultimo modello nel file xslt, quindi l'output sarà def. Questo perché i due modelli hanno la stessa priorità e se il tuo processore xslt non si ferma con un errore lo standard richiede di applicare l'ultimo:

Si tratta di un errore se questo lascia più di una regola modello corrispondente . Un processore XSLT può segnalare l'errore; se non segnala l'errore, deve ripristinarsi scegliendo, tra le regole del modello corrispondente che rimangono, quella che si verifica per ultima nel foglio di stile.

+0

+1, bella risposta –

0

Se si fissa che il codice XSLT (avete alcuni problemi di filtro) e corse, si dovrebbe vedere:

def

Perché? <xsl:apply-templates /> corrisponderà allo primo modello che soddisfi le condizioni della partita. Se si dispone di due modelli, si dovrebbe differire rispetto utilizzando tale <xsl:apply-templates>mode attributo, oppure utilizzando <xsl:template>priority attributo:

<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

Se ha vogliono i modelli da abbinare per il entrambi gli attributi, allora si avrebbe solo bisogno di regolare la match XPath per selezionare il attributi e mettere il rapporto con foo nel predicato; piuttosto che avere due modelli in conflitto che corrispondono allo fooelemento con la stessa specificità (che hanno la stessa 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

Grazie, questo è quello che volevo fare. Purtroppo non posso accettare la risposta in quanto non entra nel "perché". ;) –