XSLT中的置换 [英] Permutation in XSLT

查看:79
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆