如何在没有“select”属性的情况下强制<xsl:param>上的错误?</xsl:param>

时间:2011-06-30 07:38:25

标签: xslt xslt-1.0 xslt-2.0

如果我在没有指定值的情况下使用<xsl:param>,变换器会假定该值为空字符串。

换句话说,如果我忘记指定一个值(例如<xsl:param name="N"/>),编译器就不会发出错误信号。这可能导致我的程序无声地失败,这是一件坏事。

如何指定我的<xsl:param> 必须具有明确值?例如,此代码应该给我一个错误,因为没有指定显式值:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:call-template name="F1"></xsl:call-template>
        <html>
            <head>
                <title></title>
            </head>
            <body>stuff</body>
        </html>
    </xsl:template>
    <xsl:template name="F1">
        <xsl:param name="N"/> <!-- I Should Get An Error Here! -->
    </xsl:template>
</xsl:stylesheet>

我正在寻找XSLT 1.0和XSLT 2.0中的解决方案。

5 个答案:

答案 0 :(得分:5)

在XSLT 2.0中,您当然可以说<xsl:param required="yes">,因此问题就会消失。

答案 1 :(得分:2)

你可以用一些meta-XSLT实际做到这一点:

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

  <xsl:template match="xsl:call-template">
    <xsl:variable name="template" select="/xsl:stylesheet/xsl:template[@name=current()/@name]"/>
    <xsl:variable name="call" select="." />
    <xsl:variable name="desc">
      <xsl:value-of select="concat('call to named template &quot;',$template/@name,'&quot; in ')"/>
      <xsl:choose>
        <xsl:when test="ancestor::xsl:template/@name">
          <xsl:value-of select="concat('named template &quot;',ancestor::xsl:template/@name,'&quot;')" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="concat('template matching &quot;',ancestor::xsl:template/@match,'&quot;')" />
        </xsl:otherwise>
      </xsl:choose>
      <xsl:text>&#10;</xsl:text>
    </xsl:variable>

    <xsl:for-each select="$template/xsl:param[not(@select)]">
      <xsl:if test="not($call/xsl:with-param[@name=current()/@name])">
        <xsl:value-of select="concat('Missing parameter &quot;',@name,'&quot; in ',$desc)" />
      </xsl:if>
    </xsl:for-each>

    <xsl:for-each select="xsl:with-param">
      <xsl:if test="not($template/xsl:with-param[@name=current()/@name])">
        <xsl:value-of select="concat('Unrecognised parameter &quot;',@name,'&quot; in ',$desc)" />
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="text()" />
</xsl:stylesheet>

此样式表将任何样式表作为输入,并检查所有调用模板是否具有正确的参数,如果有任何错误则输出消息。

这显然不会将错误检查放在变换器本身,但它会一次性列出所有错误,并且可以扩展以检查其他问题。

编辑:我已经对它进行了调整以处理可选参数,并以描述错误位置的方式添加;它实际上是一个重新设计,可选参数只是计算它们将是棘手的,所以我删除了那一点。无论如何,每个错误都是逐条列出的,因此计数并不是必需的。

答案 2 :(得分:1)

<xsl:param name="foo" select="false" />
<xsl:if test="not($foo)">
  <xsl:message terminate="yes">You called me with improper params</xsl:message>
</xsl:if>

答案 3 :(得分:1)

一种简单的方法是检查输入参数不是空字符串(注释中提到的特定情况):

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template name="test">
        <xsl:param name="nodefault"/>
        <xsl:choose>
            <xsl:when test="boolean($nodefault)">
                <xsl:message>do your stuff</xsl:message>
            </xsl:when>
            <xsl:otherwise>
                <xsl:message terminate="yes">Your stuff can't be done</xsl:message>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>


    <xsl:template match="/">
        <xsl:call-template name="test"/>
    </xsl:template>

</xsl:stylesheet>

或更简单:

<xsl:template name="test">
    <xsl:param name="nodefault"/>
    <xsl:if test="not($nodefault)">
            <xsl:message terminate="yes">Your stuff can't be done</xsl:message>
    </xsl:if>
    <!-- do your stuff -->
</xsl:template>

答案 4 :(得分:1)

有一个类似的选项,您可以使用一个变量来选择被调用模板中的参数,例如:

<xsl:template match="/">
<!-- call 1 -->
<xsl:apply-templates select="//encabezado/usuario" mode="forma1">
  <xsl:with-param name="nombre" select="'wwww1'"/>
</xsl:apply-templates>
<!-- call 2 -->
<xsl:apply-templates select="//encabezado/usuario" mode="forma1">
</xsl:apply-templates>

  <xsl:template match="node()" mode="forma1">
<xsl:param name="nombre"/>
<xsl:param name="valor"/>
<xsl:variable name="nombreLocal">
  <xsl:choose>
    <xsl:when test="normalize-space($nombre)">
      <xsl:value-of select="$nombre"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="local-name()"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:value-of select ="$nombreLocal"/>
</xsl:template>