您可以使用XSLT中的函数定义自定义归类吗?

时间:2011-10-17 14:46:31

标签: xslt xslt-2.0

我想定义某个元素中使用的字符串的排序。例如,< class> Senior< / class> <类>小型< /类> <类>大二< /类> <类>大一<类> 会在课堂上描述一个合理的排序。

有没有办法使用< xsl:sort select ='class'>那将按上面给出的顺序排序?

提前致谢。

2 个答案:

答案 0 :(得分:5)

您在XSLT中可以做的是定义一个变量来表示您的自定义排序,如此

<xsl:variable name="inline-array">
   <class sort="1">Senior</class>
   <class sort="2">Junior</class>
   <class sort="3">Sophomore</class>
   <class sort="4">Freshman</class>
</xsl:variable>

然后,要访问此“数组”,您可以定义另一个变量来引用XSLT文档本身:

<xsl:variable name="array" 
   select="document('')/*/xsl:variable[@name='inline-array']/*" />

现在,您可以在排序时查找给定类名的排序属性(其中current()表示正在排序的当前节点)

<xsl:sort select="$array[. = current()/@class]/@sort" />

例如,这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:variable name="inline-array">
      <class sort="1">Senior</class>
      <class sort="2">Junior</class>
      <class sort="3">Sophomore</class>
      <class sort="4">Freshman</class>
   </xsl:variable>

   <xsl:variable name="array" 
      select="document('')/*/xsl:variable[@name='inline-array']/*"/>

   <xsl:template match="/objects">
      <xsl:copy>
         <xsl:apply-templates select="object">
            <xsl:sort select="$array[. = current()/@class]/@sort" />
         </xsl:apply-templates>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

将此应用于以下示例XML ...

<objects>
   <object id="2" name="Junior Jo" class="Junior" />
   <object id="1" name="Senior Sue" class="Senior" />
   <object id="4" name="Freshman Frank" class="Freshman" />
   <object id="3" name="Sophie Sophomore" class="Sophomore" />
</objects>

返回以下内容

<objects>
   <object id="1" name="Senior Sue" class="Senior"></object>
   <object id="2" name="Junior Jo" class="Junior"></object>
   <object id="3" name="Sophie Sophomore" class="Sophomore"></object>
   <object id="4" name="Freshman Frank" class="Freshman"></object>
</objects>

答案 1 :(得分:4)

您是否研究过Saxon的自定义排序规则?

例如,

<xsl:variable name="rules" select="'&lt; Freshman &lt; Sophomore
                                    &lt; Junior   &lt; Senior'" />

这使用该名称的Java类中的RuleBasedCollator格式。

要在排序中使用它(捎带Tim C的有用示例输入XML和样式表):

 <xsl:apply-templates select="object">
    <xsl:sort select="@class"
       collation="http://saxon.sf.net/collation?rules={encode-for-uri($rules)}"/>
 </xsl:apply-templates>

这与Tim C的解决方案具有相同的结果。 (使用Saxon PE 9.3.0.5测试。)

它不是一个xsl:函数,但它比数组提供了更多的灵活性,可以说更简洁。 AFAICT无法使用XSLT用户定义的函数创建自定义归类。既然您没有说出为什么需要xsl:function,那么很难推测出哪些替代品可以满足您的需求。

对于完全xsl:类似功能的灵活性,您可以在Java中定义自己的collat​​or;有关实现java.util.Comparator接口并在class属性中指定比较器,请参阅http://www.saxonica.com/documentation/extensibility/collation.xml