XSLT中的置换 [英] Permutation in XSLT
问题描述
我确定答案将是某种递归",尽管我正在努力做到这一点-对于一组节点,我想返回它们的所有排列:
I'm sure the answer is going to be some sort of 'recursion' I'm struggling to get quite there though -- for a set of nodes, I want to return all their permutations:
输入:
<animals>
<animal>Rabbit</animal>
<animal>Turtle</animal>
<animal>Moose</animal>
</animals>
所需的输出:
MooseRabbitTurtle
MooseTurtleRabbit
RabbitMooseTurtle
RabbitTurtleMoose
TurtleMooseRabbit
TurtleRabbitMoose
请注意按字母顺序排序,但是如果不可能,我可以不用它.另外,输入节点永远不会只有3个,因此理想情况下,它可以与任意数量的节点一起使用
Note the alphabetical sorting, but if that's not possible, I can live without it. Also, there won't always be 3 input nodes, so ideally it'd work with any number of nodes
感谢您指出正确的方向!
Thanks for any pointing in the right directions!
推荐答案
以下是示例XSLT 2.0样式表
Here is an example XSLT 2.0 stylesheet
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf"
version="2.0">
<xsl:output indent="yes"/>
<xsl:function name="mf:permute" as="item()*">
<xsl:param name="head" as="item()*"/>
<xsl:param name="tail" as="item()*"/>
<xsl:choose>
<xsl:when test="count($tail) eq 1">
<permutation>
<xsl:for-each select="$head, $tail">
<item>
<xsl:value-of select="."/>
</item>
</xsl:for-each>
</permutation>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="for $pos in (1 to count($tail)) return mf:permute(($head, $tail[$pos]), $tail[position() ne $pos])"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="mf:permutations" as="element(permutations)">
<xsl:param name="input" as="item()*"/>
<permutations>
<xsl:sequence select="for $pos in (1 to count($input)) return mf:permute($input[$pos], $input[position() ne $pos])"/>
</permutations>
</xsl:function>
<xsl:template match="animals">
<xsl:variable name="sorted-animals" as="element(animal)*">
<xsl:perform-sort select="animal">
<xsl:sort select="."/>
</xsl:perform-sort>
</xsl:variable>
<xsl:copy-of select="mf:permutations($sorted-animals)"/>
</xsl:template>
</xsl:stylesheet>
转换输入
<animals>
<animal>Rabbit</animal>
<animal>Turtle</animal>
<animal>Moose</animal>
</animals>
进入输出
<permutations>
<permutation>
<item>Moose</item>
<item>Rabbit</item>
<item>Turtle</item>
</permutation>
<permutation>
<item>Moose</item>
<item>Turtle</item>
<item>Rabbit</item>
</permutation>
<permutation>
<item>Rabbit</item>
<item>Moose</item>
<item>Turtle</item>
</permutation>
<permutation>
<item>Rabbit</item>
<item>Turtle</item>
<item>Moose</item>
</permutation>
<permutation>
<item>Turtle</item>
<item>Moose</item>
<item>Rabbit</item>
</permutation>
<permutation>
<item>Turtle</item>
<item>Rabbit</item>
<item>Moose</item>
</permutation>
</permutations>
函数mf:permutations
获取输入序列(可以在将其传递给函数之前对其进行排序),然后为该序列中的每个项目计算由该项目和递归调用形成的序列的可能排列传递除项目之外的序列.
The function mf:permutations
takes the input sequence (which can be sorted as shown before passing it to the function) and then computes the for each item in the sequence the possible permutations of the sequence formed by the item and a recursive call passing the sequence except the item.
使用Saxon 9.7支持的XSLT 3.0,我们可以缩短代码并返回数组序列,而不是带有排列的XML结构:
With XSLT 3.0 as supported by Saxon 9.7 we could shorten the code and return a sequence of arrays instead of an XML structure with the permutations:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs math array mf"
version="3.0">
<xsl:output method="adaptive"/>
<xsl:function name="mf:permute" as="array(*)*">
<xsl:param name="head" as="array(*)"/>
<xsl:param name="tail" as="item()*"/>
<xsl:sequence select="if (count($tail) eq 1)
then array:append($head, $tail)
else for $pos in (1 to count($tail)) return mf:permute(array:append($head, $tail[$pos]), $tail[position() ne $pos])"/>
</xsl:function>
<xsl:function name="mf:permutations" as="array(*)*">
<xsl:param name="input" as="xs:untypedAtomic*"/>
<xsl:sequence select="mf:permute([], $input)"/>
</xsl:function>
<xsl:template match="animals">
<xsl:sequence select="mf:permutations(sort(animal))"/>
</xsl:template>
</xsl:stylesheet>
这样结果就是
["Moose","Rabbit","Turtle"]
["Moose","Turtle","Rabbit"]
["Rabbit","Moose","Turtle"]
["Rabbit","Turtle","Moose"]
["Turtle","Moose","Rabbit"]
["Turtle","Rabbit","Moose"]
这篇关于XSLT中的置换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!