XSLT:在xls中使用参数:排序属性(动态排序)

时间:2010-03-27 13:41:26

标签: php xslt sorting parameters

如何将参数应用于select元素中的orderxsl:sort属性?我喜欢用PHP做这个动态:

$xsl = new XSLTProcessor();
$xslDoc = new DOMDocument(); 
$xslDoc->load( $this->_xslFilePath );
$xsl->importStyleSheet( $xslDoc );
$xsl->setParameter( '', 'sortBy', 'viewCount' );
$xsl->setParameter( '', 'order', 'descending' );

但我现在首先要知道如何让它发挥作用。我尝试了以下内容,但它给了我一个'编译错误':'无效值$ order for order'。 $sortBy似乎也没有做任何事情:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="sortBy" select="viewCount"/>
<xsl:param name="order" select="descending"/>
<xsl:template match="/">
    <media>
    <xsl:for-each select="media/medium">
    <xsl:sort select="$sortBy" order="$order"/>
        // <someoutput>
    </xsl:for-each>
    </media>
</xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:9)

您接近正确的解决方案,但存在一些问题:

  1. <xsl:param name="sortBy" select="viewCount"/> 这将$sortBy参数定义为当前节点(文档节点)的viewCount子节点的值。由于top元素未命名为viewCount,因此定义的$sortBy参数根本没有值。

  2. <xsl:param name="order" select="descending"/> 同上。

  3. <xsl:sort select="$sortBy" order="$order"/> 即使上面的问题1.和2.已修复,此xslt指令仍然存在问题。它将order属性的值指定为文字字符串'$order' - 而不是参数$order的值。在XSLT中执行此操作的方法是使用AVT(属性值模板)。每当我们想要在属性值中指定我们希望将特定字符串作为XPath表达式进行计算时,该字符串必须用大括号括起来。

  4. 因此,order属性应指定为:order = '{$order}'

    不幸的是,AVT不能用于select属性(XSLT规范中的另一条规则)。

    指定select属性值的方法有点棘手:

    select='*[name()=$sortBy]'这说:按子元素排序,其名称与变量$sortBy的值相同。

    将所有这些放在一起,这是纠正的转换

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:strip-space elements="*"/>
    
     <xsl:param name="sortBy" select="'viewCount'"/>
     <xsl:param name="order" select="'descending'"/>
    
     <xsl:template match="/">
        <media>
          <xsl:for-each select="media/medium">
            <xsl:sort select="*[name()=$sortBy]" order="{$order}"/>
    
            <xsl:copy-of select="."/>
          </xsl:for-each>
        </media>
     </xsl:template>
    </xsl:stylesheet>
    

    将此转换应用于以下XML文档

    <media>
     <medium>
       <viewCount>2</viewCount>
     </medium>
     <medium>
       <viewCount>1</viewCount>
     </medium>
     <medium>
       <viewCount>5</viewCount>
     </medium>
    </media>
    

    产生了正确的结果

    <media>
       <medium>
          <viewCount>5</viewCount>
       </medium>
       <medium>
          <viewCount>2</viewCount>
       </medium>
       <medium>
          <viewCount>1</viewCount>
       </medium>
    </media>