2010-07-02 24 views
6
<xsl:choose> 
    <xsl:when test="long convoluted expression"> 
     <xsl:element name="Class">123</xsl:element> 
     <a lot more xsl:elements> 
    </xsl:when> 
    <xsl:when test="next very long expression"> 
     <xml:element name="Class">124</xsl:element> 
     <a lot more xsl:elements> 
    </xsl:when> 
    <tens of more similar xsl:when> 
</xsl:choose> 

C'è un modo per semplificare il codice sopra con condizionali? Per ogni valore di classe assegnato agli oggetti, ne seguono decine di righe con attributi aggiuntivi. Questi attributi formano insiemi in base al valore della classe. La classe 0-99 ha un set di tag extra, classe 100-199 al secondo, che formano un incubo di manutenzione quando uno di questi set di tag extra cambia.Condizioni XSLT/ambito variabile

Stavo considerando una soluzione come questa:

<xsl:choose> 
    <xsl:when test="long convoluted expression"> 
     <xml:element name="Class">123</xsl:element> 
     <xsl:variable name="outputclass" select="123"> 
    </xml:when> 
    <xsl:when test="next very long expression"> 
     <xml:element name="Class">124</xsl:element> 
     <xsl:variable name="outputclass" select="124"> 
    </xsl:when> 
</xsl:choose> 
<xsl:choose> 
    <xsl:when test="$outputclass > 99"> 
     <xml:elements for classes 100-199 here> 
    </xsl:when> 
<xsl:choose> 

Ma naturalmente questo non riesce, come la variabile outputclass non è nello stesso ambito. C'è un modo per aggirare questo?

+0

Questo è confuso.Potrebbe essere più chiaro se si aggiunge un documento di input e output di esempio. –

+0

Buona domanda (+1). Vedi la * migliore * migliore soluzione nella mia risposta - con codice completo e spiegazioni. :) –

risposta

6

La migliore soluzione a questo problema è ben noto:

<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="/"> 
    <xsl:variable name="voutType"> 
     <xsl:choose> 
     <xsl:when test="long convoluted expression">123</xsl:when> 
     <xsl:when test="next very long expression">124</xsl:when> 
     <!-- Etcetera ... --> 
     </xsl:choose> 
    </xsl:variable> 

    <Class><xsl:value-of select="$voutType"</Class> 
     <xsl:choose> 
      <xsl:when test="not($voutType > 99)"> 
       <!-- elements for classes 0 - 99 here --> 
      </xsl:when> 
      <xsl:otherwise> 
       <!-- elements for classes 100-199 here --> 
      </xsl:otherwise> 
     <xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

Do atto:

  1. Al fine di dare valori ad una variabile ($voutType), il L'istruzione <xsl:choose> deve essere all'interno del il corpo del <xsl:variable>

  2. Hai solo bisogno di specificare l'elemento <Class> volta - al di fuori di tutto il resto.

  3. Non è necessario utilizzare <xsl:element> se il nome dell'elemento è noto.

+0

Questa è una bellissima soluzione. Facile da mantenere come le altre soluzioni, ma anche più breve. Che tu possa nidificare scegli dentro una variabile che non conoscevo. Grazie! – diskis

+0

@diskis: Sono davvero felice che tu abbia rifiutato la mia risposta. Non sembrava sufficiente, ma ho pensato che potesse farti andare nella giusta direzione. Questo sicuramente sembra essere il modo migliore. – MJB

+0

che cosa rende "ben noto" qualsiasi soluzione? – n611x007

0

Ho eseguito XSLT solo alcune volte, ma ogni volta sembra un enorme incubo di manutenzione. Ad ogni modo, penso che si possa impostare una variabile che dica quale sia la classe, e quindi chiama una funzione come xsl: template corrisponde alla classe come arg. Dichiareresti quella funzione come xsl: nome del modello, perché non vuoi abbinarlo automaticamente. All'interno della funzione dovresti essere in grado di codificare quei 100 valori. Non sono sicuro se questo aiuta, ma organizza il codice in un modo che potrebbe.

+0

Sì, grazie. Test rapidi dimostrano che questo funzionerà perfettamente per i miei scopi. Ora solo per rispolverare la sintassi xml: with-param, e andrò bene con alcuni template in meno. – diskis

1

Se si sta cercando di rendere più facile per specificare una serie di attributi (! non tag alias elementi), poi suona per me come set di attributi sono quello che ti serve, e non potrebbe essere necessario variabili:

http://www.w3.org/TR/xslt#attribute-sets

ciò presuppone che l'attributo valori stessi non dipendono valore della classe; solo la loro presenza è.

Se gli elementi sono davvero ciò che intendi, prova a utilizzare i modelli nominati con un parametro di input. Al livello superiore del foglio di stile:

<xsl:template name="classdef"> 
    <xsl:param name="classid"/> 
    <!-- Note: I put the class elem in here so I don't have to 
     write individual class ids more than once --> 
    <xsl:element name="Class"><xsl:value-of select="$classid"/></xsl:element> 
    <xsl:choose> 
    <xsl:when test="$classid > 99"> 
     ... 
    </xsl:when> 
    </xsl:choose> 
</xsl:template> 

e nel tuo altro modello:

<xsl:call-template name="classdef"> 
    <xsl:with-param name="classid">124</xsl:with-param> 
</xsl:call-template> 

Vedi http://www.w3.org/TR/xslt#variables per più informazioni params.

+0

Grazie, questa è essenzialmente la stessa soluzione di MJB pubblicata e funzionerà perfettamente per le mie esigenze. Tornerò e ti darò un upvote quando avrò abbastanza reputazione per farlo :) – diskis