首页 > 解决方案 > XSLT if-clause with param check 进行排序

问题描述

为什么在以下代码中添加 if 子句时会出错?

如果我删除 XSLT 中的 if 子句,所有数据都可以按预期显示。

XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name = "orderTag1"/>
<xsl:param name = "orderTag2"/>
<xsl:param name = "orderType1"/>
<xsl:param name = "orderType2"/>

<xsl:template match="/">
  <table>
    <xsl:for-each select="*/item">
        <xsl:if test="$orderTag1 != ''">
            <xsl:sort select="*[name()=$orderTag1]" order="{$orderType1}"/>
        </xsl:if>
        <xsl:if test="$orderTag2 != ''">
            <xsl:sort select="*[name()=$orderTag2]" order="{$orderType2}"/>
        </xsl:if>
        <tr>
            <xsl:apply-templates/>
        </tr>
    </xsl:for-each>
  </table>
  </xsl:template>
  <xsl:template match="*[not(*)]">
    <td>
        <xsl:value-of select="."/>
    </td>
  </xsl:template>
</xsl:stylesheet>

Javascript

var xsl = loadXMLDoc("my_xml_transformer.xsl");
var xmlDoc = loadXMLDoc("my_xml.xml");
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
xsltProcessor.setParameter(null, "orderTag1", "type");
xsltProcessor.setParameter(null, "orderTag2", "StationName");
xsltProcessor.setParameter(null, "orderType1", "ascending");
xsltProcessor.setParameter(null, "orderType2", "ascending");
var resultDocument = xsltProcessor.transformToFragment(xmlDoc, document);
document.getElementById("myTable").appendChild(resultDocument);

编辑~

我使用记事本和 chrome 开发一个 javascript 网站,以便在设置 orderTag1 或 2 时对数据进行排序。

编辑~

修改为将 if 子句放在 for-each 之外。问题已解决。

<xsl:if test="$orderTag1 != '' and $orderTag2 = ''">
    <xsl:for-each select="*/item">
        <xsl:sort select="*[name()=$orderTag1]" order="{$orderType1}"/>
            <tr>
                <xsl:apply-templates/>
            </tr>
    </xsl:for-each>
</xsl:if>

标签: javascriptxmlxslt

解决方案


你还没有说你实际上得到了什么错误,但它应该是一个错误'xsl:sort' cannot be a child of the 'xsl:if' element.。这正是它所说的。xsl:sort应该是xsl:for-eachor的孩子xsl:apply-templates,not xsl:if

您也没有说您想用 XSLT 实现什么,但看起来您希望您的排序是可配置的,基于参数。如果是这样,你可以这样做......

<xsl:for-each select="*/item">
    <xsl:sort select="*[name()=$orderTag1]" order="{$orderType1}"/>
    <xsl:sort select="*[name()=$orderTag2]" order="{$orderType2}"/>
    <tr>
        <xsl:apply-templates/>
    </tr>
</xsl:for-each>

如果未指定$orderTag1and$orderTag2并且未指定,则没有节点将匹配,并且不会对任何内容进行排序。唯一要记住的是 orderTypes 需要有默认值

<xsl:param name = "orderType1" select="'ascending'" />
<xsl:param name = "orderType2" select="'ascending'" />

例如,试试这个 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name = "orderTag1"/>
<xsl:param name = "orderTag2"/>
<xsl:param name = "orderType1" select="'ascending'" />
<xsl:param name = "orderType2" select="'ascending'" />

<xsl:template match="/">
  <table>
    <xsl:for-each select="*/item">
        <xsl:sort select="*[name()=$orderTag1]" order="{$orderType1}"/>
        <xsl:sort select="*[name()=$orderTag2]" order="{$orderType2}"/>
        <tr>
            <xsl:apply-templates/>
        </tr>
    </xsl:for-each>
  </table>
  </xsl:template>

  <xsl:template match="*[not(*)]">
    <td>
        <xsl:value-of select="."/>
    </td>
  </xsl:template>
</xsl:stylesheet>

或者,如果您想确保始终正确设置订单类型,您可以更加健壮,如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name = "orderTag1"/>
<xsl:param name = "orderTag2"/>
<xsl:param name = "orderType1" />
<xsl:param name = "orderType2" />

<xsl:template match="/">
  <table>
    <xsl:variable name="ensureOrderType1">
        <xsl:choose>
            <xsl:when test="$orderType1 != 'ascending' and $orderType1 != 'descending'">ascending</xsl:when>
            <xsl:otherwise><xsl:value-of select="$orderType1" /></xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="ensureOrderType2">
        <xsl:choose>
            <xsl:when test="$orderType2 != 'ascending' and $orderType2 != 'descending'">ascending</xsl:when>
            <xsl:otherwise><xsl:value-of select="$orderType2" /></xsl:otherwise>
        </xsl:choose>
    </xsl:variable>


    <xsl:for-each select="*/item">
        <xsl:sort select="*[name()=$orderTag1]" order="{$ensureOrderType1}"/>
        <xsl:sort select="*[name()=$orderTag2]" order="{$ensureOrderType2}"/>
        <tr>
            <xsl:apply-templates/>
        </tr>
    </xsl:for-each>
  </table>
  </xsl:template>

  <xsl:template match="*[not(*)]">
    <td>
        <xsl:value-of select="."/>
    </td>
  </xsl:template>
</xsl:stylesheet>

推荐阅读