2009-09-07 11 views
7

Ho una domanda relativa ad una sorta di funzione casuale di XSLT.Seleziona in modo casuale un nodo in XSLT

Ho un file XML che molto semplificato simile al seguente:

<node id="1198"> 
    <node id="1201"> 
    <data alias="name">Flemming</data> 
    <data alias="picture">1200</data> 
    </node> 
    <node id="1207"> 
    <data alias="name">John</data> 
    <data alias="picture">1205</data> 
    </node> 
    <node id="1208"> 
    <data alias="name">Michael</data> 
    <data alias="picture">1206</data> 
    </node> 
</node> 

Vorrei avere un po 'XSLT, che ramdomly ha preso uno dei nodi ID e metterlo in una variabile chiamata "choosenNode ". Ti piace questa, se il nodo con l'ID del 1207 è stato quello selezionato:

<xsl:variable name="choosenNode" value="1207" /> 

Come posso fare questo? Esiste una funzione casuale in XSLT? A proposito, vorrei che la variabile venisse aggiornata su ogni pagina in cui è incluso XSLT.

E lavoro in Umbraco CMS, se questo ti aiuta ragazzi.

Grazie, -Kim

risposta

7

In Umbraco si può fare qualcosa di simile:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE xsl:Stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]> 
<xsl:stylesheet 
version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxml="urn:schemas-microsoft-com:xslt" 
xmlns:umbraco.library="urn:umbraco.library" 
xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" 
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltMath"> 

<xsl:output method="xml" omit-xml-declaration="yes"/> 

<xsl:param name="currentPage"/> 

<!-- This should probably be a macro parameter so you can use this elsewhere--> 
<xsl:variable name="parentNode" select="1048"/> 

<xsl:template match="/"> 

     <xsl:variable name="numberOfNodes" select="count(umbraco.library:GetXmlNodeById($parentNode)/node)"/> 

     <xsl:variable name="randomPosition" select="floor(Exslt.ExsltMath:random() * $numberOfNodes) + 1"/> 

     <xsl:variable name="randomNode" select="umbraco.library:GetXmlNodeById($parentNode)/node [position() = $randomPosition]"/> 

     <!-- 
      You now have the node in the $randomNode variable 
      If you just want the id then you can do an XPath query on the variable 
      or you can modify the XPath above to get the property you are after rather than 
      the whole node 
     --> 

    <xsl:value-of select="$randomNode/@nodeName" /> 

</xsl:template> 
</xsl:stylesheet> 

Spero che questo aiuti.

Tim

+0

Questo sembra piuttosto interessante, Tim potrebbe essere una buona soluzione. Verificherò domani, quindi riceverai una risposta corretta se funziona: D Grazie ... –

+0

OK - Non ho effettivamente controllato il codice - l'ho appena scritto dalla parte superiore della mia testa , quindi attenzione ai bug! –

+0

OOOPS: alcuni piccoli errori di battitura. L'ho riordinato e controllato che funzioni in una delle mie installazioni Umbraco. Ho anche aggiunto una riga che mostra come afferrare un valore. –

0

Come numero casuale in XSLT non è un compito facile.

c'è qualcosa che può fare, ma si deve probabilmente perché dia il seme generatore casuale http://fxsl.sourceforge.net/articles/Random/Casting%20the%20Dice%20with%20FXSL-htm.htm

Forse il processore che si sta utilizzando per fare XSL trasformazione ha la capacità di estendere le espressioni XSL con le funzioni esterne. In tal caso, forse puoi usare la funzione casuale esterna.

+0

Umbraco ha accesso alla propria libreria di funzioni di estensione e quelli di Microsoft all'interno del processore XSLT così, quel problema è risolto. Sebbene lo scripting all'interno del processore XSLT possa martellare il server –

0

Tutto ciò che serve è un generatore di numeri casuali. Non c'è nessuno in XSLT quindi il numero casuale deve essere fornito da qualcosa al di fuori di XSLT. Dovrai chiamare un metodo da una libreria esterna per fare ciò e l'implementazione di questa libreria dipenderà dal fatto che tu sia su Windows (.NET o WIN32) o Linux e sul processore XSLT. XSLT può fare matematica ma manca un sacco di funzioni relative alla data/ora che capita di includere un generatore di numeri casuali.

Tuttavia, XSLT ha una funzione XPath denominata generate-id() che genererà un ID univoco. Se potessi trasformare questo in un nuimber in qualche modo, potrebbe essere usato per creare un numero casuale, anche se sarebbe prevedibile e alcuni numeri potrebbero verificarsi più spesso di altri. Non lo userei.

Se si utilizza MSXSL per elaborare il foglio di stile, è possibile includere JavaScript per generare numeri casuali all'interno del foglio di stile. (O script C# quando si utilizza .NET.)

Ottenere il nodo stesso è facile, una volta che si conosce il numero di nodi figlio. Basta chiedere il nodo nella posizione casuale. Qualcosa come/node/node [5] restituirebbe il quinto nodo.

0

Questa soluzione funziona in uno script di shell che utilizza xsltproc testo e le utility.

RandomElement=$(xsltproc style.xsl file.xml | tr ' ' '\n' | sort -uR | head -n 1) 

Si presume che il file style.xsl selezionerà l'elemento necessario impostare e restituire i suoi valori, uno per riga nel file di testo di output. Il comando tr dovrebbe mettere ogni elemento su una riga separata. sort -uR dovrebbe produrre un elenco casuale unico degli elementi selezionati dai comandi del foglio di stile style.xsl. Lo head -n 1 estrae quindi la prima riga dell'elenco casuale univoco.

0

Quanto segue presuppone che il processore XSLT supporti le estensioni EXSLT (ad es. Xsltproc).

Questo restituirà il contenuto del "nodo" selezionato casualmente (deve essere un figlio di un "nodo", cioè un elemento "nodo/nodo").

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:math="http://exslt.org/math" 
    extension-element-prefixes="math" > 

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

<xsl:template match="node"> 
    <xsl:variable name='selected'> 
    <xsl:value-of select="ceiling(math:random() * count(node))"/> 
    </xsl:variable> 
    <xsl:copy-of select="node[position() = $selected]"/> 
</xsl:template> 
</xsl:stylesheet> 

Questo potrebbe essere un frammento utile per elaborare il contenuto del nodo selezionato:

<xsl:variable name="randomNode" select="node[position() = $selectNode]"/> 
<id><xsl:value-of select="$randomNode/@id"/></id> 
<name><xsl:value-of select="$randomNode/data[@alias='name']"/></name> 
<picture><xsl:value-of select="$randomNode/data[@alias='picture']"/></picture> 

noti che quanto sopra non ritorno, la definizione xslt della variabile, esso utilizza quella variabile per copiare il nodo selezionato.

Per impostare l'attributo 'valore' di un xsl: elemento variabile, provare un modello di attributi come:

<xsl:variable name='chosenNode' value='{node[position() = $selected]/@id}'/>