在XSLT中随机选择一个节点

时间:2009-09-07 12:16:31

标签: xslt umbraco xml random

我对XSLT中的某种随机函数有疑问。

我有一个非常简化的XML文件,类似于:

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

我想要一些XSLT,ramdomly接受其中一个节点id并将其放入一个名为“choosenNode”的变量中。 像这样,如果ID为1207的节点是选定的节点:

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

我该怎么做? XSLT中是否有随机函数? 顺便说一句,我希望在包含XSLT的每个页面上刷新变量。

我在Umbraco CMS工作,如果这对你们有帮助的话。

谢谢, -Kim

5 个答案:

答案 0 :(得分:7)

在Umbraco你可以这样做:

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

希望这有帮助。

答案 1 :(得分:0)

在xslt中获取随机数并非易事。

有些东西可以做到但你可能必须为随机生成器提供种子 http://fxsl.sourceforge.net/articles/Random/Casting%20the%20Dice%20with%20FXSL-htm.htm

也许你用来做xsl转换的处理器有能力用外部函数扩展xsl表达式。在这种情况下,你可以使用外部随机函数。

答案 2 :(得分:0)

您只需要一个随机数生成器。在XSLT中没有,因此随机数必须由XSLT之外的东西提供。您需要从外部库调用方法来执行此操作,并且此库的实现将取决于您是在Windows(.NET或WIN32)还是Linux和XSLT处理器上。 XSLT可以做数学,但它缺少很多与日期/时间相关的函数,恰好包括一个随机数生成器。

但是,XSLT确实有一个名为generate-id()的XPath函数,它将生成一个唯一的ID。如果你可以以某种方式将其转换为一个nuimber,它可能会被用来创建一个随机数,虽然它是可预测的,有些数字可能比其他数字更频繁地出现。 我不会用它。

如果使用MSXSL处理样式表,则可以包含JavaScript以在样式表中生成随机数。 (或使用.NET时的C#脚本。)

一旦知道子节点的数量,获取节点本身就很容易。只需在随机位置询问节点。 / node / node [5]之类的东西会返回第5个节点。

答案 3 :(得分:0)

此解决方案适用于使用xsltproc和文本实用程序的shell脚本。

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

假设style.xsl文件将选择所需的元素集并返回它的值,输出文本文件中每行一个。 tr命令应该将每个元素放在一个单独的行上。 sort -uR应生成由style.xsl样式表命令选择的元素的唯一随机列表。 head -n 1然后拉出唯一随机列表的第一行。

答案 4 :(得分:0)

以下假设XSLT处理器支持EXSLT扩展(例如,xsltproc)。

这将返回随机选择的“节点”的内容(它必须是“节点”的子节点,即“节点/节点”元素)。

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

这可能是处理所选节点内容的有用代码段:

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

请注意,上面没有返回变量的xslt定义,它使用该变量来复制所选节点。

要设置xsl:variable元素的'value'属性,请尝试使用以下属性模板:

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