2009-09-07 25 views
7

Tengo una pregunta sobre algún tipo de función aleatoria en XSLT.Elegir al azar un nodo en XSLT

Tengo un archivo XML que muy simplificada similar a esto:

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

me gustaría tener un poco de XSLT, que ramdomly tomó uno de los nodos de identificación y ponerlo en una variable llamada "choosenNode ". De esta manera, si el nodo con el ID de 1207 fue el seleccionado:

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

¿Cómo puedo hacer esto? ¿Hay una función aleatoria en XSLT? Por cierto, me gustaría que la variable se actualice en cada página donde se incluye XSLT.

Y trabajo en Umbraco CMS, si eso les ayuda chicos.

Gracias, -Kim

Respuesta

7

En Umbraco se puede hacer algo como esto:

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

Espero que esto ayude.

Tim

+0

Eso se ve muy bien Tim, esta podría ser una buena solución. Lo veré mañana, así obtendrás una respuesta correcta si funciona: D Gracias ... –

+0

OK - Realmente no he comprobado el código, simplemente lo escribí casi en la parte superior de mi cabeza , así que ¡cuidado con los errores! –

+0

OOOPS - algunos pequeños errores tipográficos allí. Lo he arreglado y comprobé que funciona en una de mis instalaciones de Umbraco. También agregué una línea que muestra cómo obtener un valor. –

0

Obtención de números aleatorios en XSLT no es una tarea fácil.

Hay algo que puede hacerlo, pero es probable que tiene que proporcionar la semilla para el generador aleatorio http://fxsl.sourceforge.net/articles/Random/Casting%20the%20Dice%20with%20FXSL-htm.htm

Tal vez el procesador que está utilizando para hacer la transformación XSL tiene capacidad para extender expresiones XSL con funciones externas. En ese caso, tal vez puedas usar la función aleatoria externa.

+0

Umbraco tiene acceso a su propia biblioteca de funciones de extensión y los de Microsoft dentro del procesador XSLT, por lo ese problema esta resuelto Aunque las secuencias de comandos dentro del procesador XSLT pueden dañar el servidor –

0

Todo lo que necesita es un generador de números aleatorios. No hay ninguno en XSLT, por lo tanto, el número aleatorio debe ser proporcionado por algo externo a XSLT. Tendrá que llamar a un método de una biblioteca externa para hacer esto y la implementación de esta biblioteca dependerá de si está en Windows (.NET o WIN32) o Linux y el procesador XSLT. XSLT puede hacer cálculos matemáticos pero le faltan muchas funciones relacionadas con la fecha/hora que incluyen un generador de números aleatorios.

Sin embargo, XSLT tiene una función XPath llamada generate-id() que generará una ID única. Si pudieras transformar esto en un nuimber de alguna manera, podría usarse para crear un número aleatorio, aunque sería predecible y algunos números podrían ocurrir más a menudo que otros. No lo usaría.

Si usa MSXSL para procesar su hoja de estilos, puede incluir JavaScript para generar números aleatorios dentro de la hoja de estilos. (O script C# cuando se utiliza .NET).

Obtener el nodo en sí es fácil, una vez que conoce la cantidad de nodos secundarios. Solo pregunta por el nodo en la posición aleatoria. Algo como/node/node [5] devolvería el 5º nodo.

0

Esta solución funciona en un script de shell que utiliza xsltproc de texto y los servicios públicos.

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

Se supone que el archivo style.xsl seleccionará el elemento necesario establecer y devolver valores que es, uno por línea en el archivo de texto de salida. El comando tr debe poner cada elemento en una línea separada. El sort -uR debe producir una lista única y aleatoria de los elementos seleccionados por los comandos de la hoja de estilo style.xsl. El head -n 1 luego saca la primera línea de la lista única y aleatoria.

0

Lo siguiente asume que el procesador XSLT admite extensiones EXSLT (por ejemplo, xsltproc).

Esto devolverá el contenido del "nodo" seleccionado al azar (debe ser un elemento secundario de un "nodo", es decir, 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> 

Esto podría ser un fragmento útil para procesar el contenido del nodo seleccionado:

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

Tenga en cuenta que lo anterior no devuelve la definición XSLT de la variable, se utiliza esa variable para copiar el nodo seleccionado

para establecer el atributo 'valor' de un elemento xsl: variable tratar una plantilla de atributos como:

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