2012-01-31 13 views
6

Voglio usare l'attributo @sourcename nel modo seguente, come vantaggio:XSLT: l'assegnazione di variabili pari a uno dei due casi

Se @sourcename ha un punto in essa, dovrebbe essere assegnata la parte prima del primo punto a $srcgroup e la parte dopo il primo punto deve essere assegnato a $srcword.

Altrimenti $srcgroup deve essere impostato su @sourcename e $srcword dovrebbe essere la stringa vuota.

In entrambi i casi, voglio fare le stesse cose utilizzando $srcgroup e $srcword.

Ho provato questo con il seguente frammento:

<xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')">  
    <xsl:variable name="srcgroup" select="substring-before(@sourcename, '.')"/> 
    <xsl:variable name="srcword" select="substring-after(@sourcename, '.')" /> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:variable name="srcgroup" select="@sourcename" /> 
    <xsl:variable name="srcword" />      
    </xsl:otherwise> 
</xsl:choose> 

<foo group="{$srcgroup}" word="{$srcword}" /> 
<!-- there's some other more complicated users of $srcgroup and $srcword --> 

Il problema è che ottengo un errore (questo sta usando JAXP in Java):

ERROR: [my xsl file]: line 35: Variable or parameter 'srcgroup' is undefined.' 
FATAL ERROR: 'Could not compile stylesheet' 
Exception in thread "main" javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet 
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:825) 

se ho capito bene, ho' m indovinando che le variabili hanno solo lo scopo del caso particolare nel blocco <xsl:choose>. C'è un modo per aggirarlo? Non voglio dover ripetere il mio altro codice due volte.


p.s. Ho trovato una soluzione:

<xsl:variable name="srcgroup" select="substring-before(concat(@sourcename, '.'), '.')" /> 
<xsl:variable name="srcword" select="substring-after(@sourcename, '.')" /> 

ma ho ancora voglia di sapere come risolvere mia domanda iniziale, per riferimento futuro.

risposta

5

Basta usare (non condizionali necessarie):

<xsl:variable name="srcgroup" select= 
    "substring-before(concat(@sourcename, '.'), '.')"/> 

    <xsl:variable name="srcword" select= 
    "substring-after(@sourcename, '.')"/> 

esempio completo:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="x|y"> 
    <xsl:variable name="srcgroup" select= 
    "substring-before(concat(@sourcename, '.'), '.')"/> 

    <xsl:variable name="srcword" select= 
    "substring-after(@sourcename, '.')"/> 

    $srcgroup = "<xsl:value-of select="$srcgroup"/>" 
    $srcword = "<xsl:value-of select="$srcword"/>" 
</xsl:template> 
</xsl:stylesheet> 

quando applicato su questo documento XML:

<t> 
    <x sourcename="a.b.c"/> 
    <y sourcename="noDots"/> 
</t> 

il risultato voluto è prodotto in entrambi i casi:

$srcgroup = "a" 
    $srcword = "b.c" 

    $srcgroup = "noDots" 
    $srcword = "" 

Spiegazione: la logica non necessaria evitato ponendo un sentinella.


Confrontare questo al molto più verboso condizionale sintassi:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="x|y"> 
    <xsl:variable name="srcgroup"> 
    <xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')"> 
     <xsl:value-of select="substring-before(@sourcename, '.')"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="@sourcename"/> 
    </xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <xsl:variable name="srcword"> 
    <xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')"> 
     <xsl:value-of select="substring-after(@sourcename, '.')"/> 
    </xsl:when> 
    <xsl:otherwise/> 
    </xsl:choose> 
    </xsl:variable> 

    $srcgroup = "<xsl:value-of select="$srcgroup"/>" 
    $srcword = "<xsl:value-of select="$srcword"/>" 
</xsl:template> 
</xsl:stylesheet> 

Quando questa trasformazione più prolisso viene applicato sul documento stesso XML (sopra), di nuovo lo stesso risultato corretto viene prodotto:

$srcgroup = "a" 
    $srcword = "b.c" 

    $srcgroup = "noDots" 
    $srcword = "" 
+0

Se leggi il mio commento alla fine del mio post, vedrai che l'ho capito ... questo è utile per gestire quel caso specifico, ma non risponde alla mia domanda su come assegnare una variabile in modo condizionale. –

+0

A proposito, hai un errore - non dovresti usare il concat nel caso 'sottostringa-dopo', poiché produce un punto in più alla fine di' srcword' nel caso non vuoto. –

+0

@JasonS: ho risolto la mia risposta. E sì, risponde esattamente alla domanda su come definire una variabile in modo condizionato. Come puoi vedere, non sono necessari condizionali per definire le variabili nel modo desiderato. –

5

E 'più simile a questo:

<xsl:variable name="srcgroup"> 
<xsl:choose...> 
    ... 
</xsl:choose> 
</xsl:variable> 
+0

+1, ma potresti aiutarmi con la sintassi? Non ho familiarità con l'uso di '' senza un 'select =' –

+0

Il contenuto del tag è il valore della variabile. Metti '' dove devi assegnare il compito nel ''. –

+0

E guarda qui - http://www.w3.org/TR/xslt - ogniqualvolta sorgano dei dubbi, una risorsa davvero utile. –