2009-09-07 120 views
7

我对XSLT中的某种随机函数有疑问。随机选择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变量”。 这样,如果与1207的ID的节点被选择的一个:

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

我怎样才能做到这一点? XSLT中是否有随机函数?顺便说一下,我希望在每个包含XSLT的页面上刷新变量。

我在Umbraco CMS工作,如果这可以帮助你们。

感谢, -Kim

回答

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> 

希望这有助于。

Tim

+0

Tim看起来很酷,这可能是一个很好的解决方案。我会明天检查出来,所以如果它能正常工作,你会得到一个正确的答案:D 谢谢... – 2009-09-07 15:24:58

+0

好的 - 我没有真正检查过代码 - 只是输入了它,几乎离开了我的头顶,所以要小心错误! – 2009-09-07 15:27:51

+0

OOOPS - 在那里有几个小错别字。我已经整理过它并检查了它是否适用于我的一个Umbraco安装。我还添加了一行显示如何获取值。 – 2009-09-07 15:46:46

0

获取XSLT中的随机数是不容易的事。

有什么东西可以做,但你可能已经为随机生成 http://fxsl.sourceforge.net/articles/Random/Casting%20the%20Dice%20with%20FXSL-htm.htm

也许你正在使用做XSL转换处理器必须与外部功能扩展XSL表达能力提供种子。在这种情况下,也许你可以使用外部随机功能。

+0

一把umbraco访问其自身的扩展功能和XSLT处理器内部的微软那些库,所以该问题已解决。尽管XSLT处理器内部的脚本可以敲击服务器 – 2009-09-07 18:50:46

0

所有你需要的是一个随机数发生器。 XSLT中没有任何内容,因此随机数必须由XSLT之外的某些内容提供。您需要从外部库调用一个方法来执行此操作,并且此库的实现取决于您是在Windows(.NET或WIN32)还是Linux和XSLT处理器上。 XSLT可以做数学运算,但是它缺少很多与日期/时间相关的函数,这些函数碰巧包含一个随机数生成器。

但是,XSLT确实有一个名为generate-id()的XPath函数,它将生成一个唯一的ID。如果您可以以某种方式将其转换为裸人,它可能会用于创建一个随机数字,尽管这是可以预测的,并且一些数字可能比其他数字更频繁地出现。 我不会使用它。

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

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

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抽出唯一随机列表的第一行。

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的“价值”属性:可变元素,尝试像一个属性的模板:

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