如何测试变量是否包含元素值或字符串/数字值?(XSL 1.0)

3

我想知道如何在XSL 1.0中测试一个变量是否包含元素值或简单的字符串/数字。

<xsl:choose>
    <xsl:when test="is the variable an element">
           <!-- do some stuff -->
    </xsl:when>
    <xsl:otherwise>
           <!-- do some other stuff -->
    </xsl:otherwise>
</xsl:choose>

关于我的问题的更多细节

我有一个类似下面的XSL。有时变量可能是一个元素,有时该元素可能没有值(即nil =“true”)。这就是为什么我使用$imAStringButICouldHaveBeenAnElementForAllYouKnow[normalize-space()]测试来检查该元素是否具有值。

然而,使用Saxon 6.5.5运行此XSL会失败并显示“该值不是节点集”。我可以理解为什么会这样,因为该变量确实不是一个节点集;在此之前,我需要进行额外的检查以确认变量是否包含适当的值。

XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:variable name="imAStringButICouldHaveBeenAnElementForAllYouKnow" select="'string'"/>

    <xsl:template match="/">
        <!-- If this is an element I want to know does it have a value? -->
        <xsl:if test="$imAStringButICouldHaveBeenAnElementForAllYouKnow[normalize-space()]">
            <!-- do some stuff -->
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

你能详细解释一下什么是元素值和字符串数字吗?可以举几个例子来说明吗? - undefined
当然。元素值是一种节点,它是一个标签,看起来像<this>。它必须有一个名称和一个相关的结束标签。我可以通过在变量声明中使用select="someNodeName"属性来为变量赋予一个元素值。字符串或数字值与元素无关,只是一个独立的值。它们可以通过使用select="'I'm a string'"select="1"来赋值给变量。 - undefined
为什么你不能检查第一个字符是否是一个开括号呢? - undefined
2
@Saksham 试一下,看看效果。 - undefined
2个回答

4
我认为用XSLT 1.0不可能实现这一点(如果被证明是错误的,我会很高兴)。对于应用于字符串的任何节点集函数,都会导致致命错误,如果它作用于元素,则无法工作。
你如何才能达到一个不知道变量中预先填充内容的位置?在我看来,真正的问题就在这里。
请注意,您可以使用以下方法检查文本值的存在,而不管变量内容的类型:
<xsl:if test="normalize-space($myVar)">

当变量是非空、非空格字符串或具有非空、非空格后代文本节点的元素时,此函数将返回true。


编辑:

我没有注意到您正在使用Saxon 6.5(直到Michael Kay在他的答案中指出)。在这种情况下,您可以利用EXSLT exsl:node-type()扩展函数,Saxon 6.5支持此函数,例如:

<xsl:if test="exsl:object-type($myVar)='string'">
    <!-- do something -->
</xsl:if>

或者
<xsl:if test="exsl:object-type($myVar)='node-set'">
    <!-- do something -->
</xsl:if>

谢谢你详尽的回答 @michael.hor257k,使用 normalize-space($myVar) 对我来说是理想的解决方案 :) 我对你建议中的一点很感兴趣,即我可能永远不会陷入不知道变量内容的情况,你说得很对。问题出在我使用了一个模板,该模板接受一个用于保存元素值的变量。但有时我想要对数据进行处理,所以我对元素值执行了一个子字符串操作。我相信这样可以动态地获取元素的 text() 子节点并将其转换为字符串? - undefined
我不确定我理解了。在XSLT中,变量是不可变的。如果样式表将一个元素作为变量的内容选择,那么变量的数据类型将始终是node-set。对变量应用substring()函数确实会返回一个字符串 - 但该字符串不会成为变量的内容。另一方面,如果变量被定义为选择元素文本值的子字符串,则变量的数据类型将始终是string。-- P.S. 您所称之为“元素值”的正确术语是“元素”:http://www.w3.org/TR/REC-xml/#dt-element - undefined
感谢您对术语的澄清。也许我没有表达清楚,但是您在最后一句话中所说的接近实际情况,只是有一个例外,我并不是将子字符串应用于元素的文本值,而是应用于元素本身。在这种情况下,我相信元素的text()子节点会被动态选择并转换为字符串。 - undefined
@Scribe 一个字符串函数无法应用于节点集,因此会进行隐式转换:substring(myElement, 1) 被解释为 substring(string(myElement), 1) - undefined

1

在纯XSLT 1.0中无法实现。如果您正在运行Saxon 6.5.5,则很容易切换到Saxon 9.5和XSLT 2.0,它提供了巨大的好处,除了“instance of”运算符为解决此问题提供了解决方案之外。


感谢你的回复,@Michael Kay。我非常想使用XSLT 2.0,但不幸的是,我目前没有能够更改我们现在使用的XSLT引擎的权力。将来我会考虑使用它 :) - undefined
祝你好运,希望你能找到一个能够在重要决策中发挥更大影响力的职位;-) - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接