Rather than selecting all elements in a given context, is it possible to
select a random set of a predifined number. For example given the
following XML file which could contain hundreds of images, is it
possible to output a randomly selected set of 3
<imglibrary>
<img src="1.jpg"/>
<img src="2.jpg"/>
<img src="3.jpg"/>
etc...
</imglibrary>
The output could be something like:
<img src="53"/>
<img src="74"/>
<img src="81"/>
One can use the random.xsl module of FXSL as a base and also follow the
approach taken in the randomList.xsl module.
The result is the following transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext"
<xsl:import href="random.xsl"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pSeed" select="17489"/>
<xsl:param name="pNodes" select="/*/*"/>
<xsl:param name="pnumRandoms" select="10"/>
<xsl:variable name="vnumNodes" select="count($pNodes)"/>
<xsl:template match="/">
<xsl:if test="$pnumRandoms > $vnumNodes">
<xsl:message terminate="yes">
Number of desired random nodes exceeds total number of nodes.
</xsl:message>
</xsl:if>
<xsl:variable name="vRandSequence">
<xsl:call-template name="randomSequence">
<xsl:with-param name="pLength" select="$pnumRandoms"/>
<xsl:with-param name="pSeed" select="$pSeed"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vrandInds">
<xsl:call-template name="_vScale">
<xsl:with-param name="pRandSeq"
select="ext:node-set($vRandSequence)/*"/>
<xsl:with-param name="pstartIndex"
select="$vnumNodes - $pnumRandoms"/>
<xsl:with-param name="pmaxIndex" select="$vnumNodes"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="takeNNodes">
<xsl:with-param name="pNodes" select="$pNodes"/>
<xsl:with-param name="pInds" select="ext:node-set($vrandInds)/*"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="takeNNodes">
<xsl:param name="pNodes" select="/.."/>
<xsl:param name="pInds" select="/.."/>
<xsl:if test="$pInds">
<xsl:copy-of select="$pNodes[position() = $pInds[1]]"/>
<xsl:call-template name="takeNNodes">
<xsl:with-param name="pNodes"
select="$pNodes[position() != $pInds[1]]"/>
<xsl:with-param name="pInds"
select="$pInds[position() > 1]"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="_vScale">
<xsl:param name="pRandSeq" select="/.."/>
<xsl:param name="pstartIndex" select="1"/>
<xsl:param name="pmaxIndex" select="1"/>
<xsl:if test="$pRandSeq
and
not($pmaxIndex < $pstartIndex) ">
<el>
<xsl:call-template name="_randScale">
<xsl:with-param name="arg2" select="1"/> <!--start-->
<xsl:with-param name="arg3"
select="$pmaxIndex"/> <!--end-->
<xsl:with-param name="arg1" select="$pRandSeq[1]"/>
</xsl:call-template>
</el>
<xsl:call-template name="_vScale">
<xsl:with-param name="pRandSeq"
select="$pRandSeq[position() > 1]"/>
<xsl:with-param name="pstartIndex" select="$pstartIndex"/>
<xsl:with-param name="pmaxIndex" select="$pmaxIndex - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="_randScale" >
<xsl:param name="arg2" select="0"/> <!--pStart-->
<xsl:param name="arg3" select="1"/> <!--pEnd -->
<xsl:param name="arg1"/> <!--pN -->
<xsl:value-of
select="floor( ($arg3 - $arg2 + 1) div ($modulus - 1)
* $arg1
+ $arg2
)"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following source.xml:
<imglibrary>
<img src="1.jpg"/>
<img src="2.jpg"/>
<img src="3.jpg"/>
<img src="4.jpg"/>
<img src="5.jpg"/>
<img src="6.jpg"/>
<img src="7.jpg"/>
<img src="8.jpg"/>
<img src="9.jpg"/>
<img src="10.jpg"/>
<img src="11.jpg"/>
<img src="12.jpg"/>
<img src="13.jpg"/>
<img src="14.jpg"/>
<img src="15.jpg"/>
<img src="16.jpg"/>
<img src="17.jpg"/>
<img src="18.jpg"/>
<img src="19.jpg"/>
<img src="20.jpg"/>
<img src="21.jpg"/>
<img src="22.jpg"/>
<img src="23.jpg"/>
<img src="24.jpg"/>
<img src="25.jpg"/>
<img src="26.jpg"/>
<img src="27.jpg"/>
<img src="28.jpg"/>
<img src="29.jpg"/>
<img src="30.jpg"/>
<img src="31.jpg"/>
<img src="32.jpg"/>
<img src="33.jpg"/>
<img src="34.jpg"/>
<img src="35.jpg"/>
<img src="36.jpg"/>
<img src="37.jpg"/>
<img src="38.jpg"/>
<img src="39.jpg"/>
<img src="40.jpg"/>
<img src="41.jpg"/>
<img src="42.jpg"/>
<img src="43.jpg"/>
<img src="44.jpg"/>
<img src="45.jpg"/>
<img src="46.jpg"/>
<img src="47.jpg"/>
<img src="48.jpg"/>
<img src="49.jpg"/>
<img src="50.jpg"/>
<img src="51.jpg"/>
<img src="52.jpg"/>
<img src="53.jpg"/>
<img src="54.jpg"/>
<img src="55.jpg"/>
<img src="56.jpg"/>
<img src="57.jpg"/>
<img src="58.jpg"/>
<img src="59.jpg"/>
<img src="60.jpg"/>
<img src="61.jpg"/>
<img src="62.jpg"/>
<img src="63.jpg"/>
<img src="64.jpg"/>
<img src="65.jpg"/>
<img src="66.jpg"/>
<img src="67.jpg"/>
<img src="68.jpg"/>
<img src="69.jpg"/>
<img src="70.jpg"/>
<img src="71.jpg"/>
<img src="72.jpg"/>
<img src="73.jpg"/>
<img src="74.jpg"/>
<img src="75.jpg"/>
<img src="76.jpg"/>
<img src="77.jpg"/>
<img src="78.jpg"/>
<img src="79.jpg"/>
<img src="80.jpg"/>
<img src="81.jpg"/>
<img src="82.jpg"/>
<img src="83.jpg"/>
<img src="84.jpg"/>
<img src="85.jpg"/>
<img src="86.jpg"/>
<img src="87.jpg"/>
<img src="88.jpg"/>
<img src="89.jpg"/>
<img src="90.jpg"/>
<img src="91.jpg"/>
<img src="92.jpg"/>
<img src="93.jpg"/>
<img src="94.jpg"/>
<img src="95.jpg"/>
<img src="96.jpg"/>
<img src="97.jpg"/>
<img src="98.jpg"/>
<img src="99.jpg"/>
<img src="100.jpg"/>
</imglibrary>
the following result is produced:
<img src="27.jpg" />
<img src="91.jpg" />
<img src="14.jpg" />
<img src="80.jpg" />
<img src="67.jpg" />
<img src="13.jpg" />
<img src="30.jpg" />
<img src="92.jpg" />
<img src="81.jpg" />
<img src="37.jpg" />
Here we produce 10 random nodes of the original 100 nodes.
There are three global parameters used:
<xsl:param name="pSeed" select="17489"/>
<xsl:param name="pNodes" select="*/*"/>
<xsl:param name="pnumRandoms" select="10"/>
The "pSeed" parameter may be used as is or can be passed from outside the
transformation (e.g. based on the current time).
The "pNodes" parameter is the node-set from which $pnumRandoms number of
nodes should be taken randomly.
=====
Cheers,
Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list