如果在不指定值的情况下使用<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>
我正在寻找XSLT1.0和XSLT2.0的解决方案。
在XSLT2.0中,当然可以说<xsl:param required="yes">
,这样问题就消失了。
您实际上可以使用一些元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 "',$template/@name,'" in ')"/>
<xsl:choose>
<xsl:when test="ancestor::xsl:template/@name">
<xsl:value-of select="concat('named template "',ancestor::xsl:template/@name,'"')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('template matching "',ancestor::xsl:template/@match,'"')" />
</xsl:otherwise>
</xsl:choose>
<xsl:text> </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 "',@name,'" 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 "',@name,'" in ',$desc)" />
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
该样式表将任何样式表作为输入,并检查所有调用模板是否具有正确的参数,如果有任何错误,则输出消息。
这显然不会将错误检查放在转换器本身中,但它会一次性列出所有错误,并可能扩展到检查其他问题。
编辑:我对它进行了调整,以处理可选参数,并添加了一种描述错误所在的方法;这实际上有点像重新设计,使用可选参数——简单地计算它们——会很棘手,所以我删除了这一点。无论如何,每个错误都是逐项列出的,所以计数并不是真正必要的。
<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>
一个简单的方法是检查输入参数是否为空字符串(注释中提到的特定情况(:
<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>
还有一个类似的选项,您可以使用一个变量来选择被调用模板中的参数,例如:
<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>