Xslt xsl:sequence是否始终为非空?

Xslt xsl:sequence是否始终为非空?,xslt,xpath,xslt-2.0,xsl-variable,Xslt,Xpath,Xslt 2.0,Xsl Variable,我不理解此样式表的输出: <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates select="root/sub"/> </xsl:template> <xsl:template match="sub"&g

我不理解此样式表的输出:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates select="root/sub"/>
    </xsl:template>

    <xsl:template match="sub">
        <xsl:variable name="seq">
            <xsl:sequence select="*" />
        </xsl:variable>

        <xsl:message>
            <xsl:value-of select="@id" />
            <xsl:text>: </xsl:text>
            <xsl:value-of select="count($seq)" />
        </xsl:message>
    </xsl:template>
</xsl:stylesheet>
我本来以为是这样的:

empty: 0
one: 1
two: 2
three: 3

为什么在这种情况下,
count($seq)
总是返回1?如何更改变量定义,以便我以后可以测试它是否为空?(简单的
将返回预期的答案,但不是一个选项…我想在中的
变量之间更改
,稍后测试它是否为空)。

您正在选择子节点,然后对每个节点进行计数-因此它始终为1。您需要计算孩子数,例如:

<xsl:value-of select="count($seq/*)" />

将提供您期望的输出。

让我试着回答您问题的“为什么”部分

如果您编写以下语句:

<xsl:variable name="x" select="*" />
其中变量
$x
包含一个节点序列:内容
的父节点。在这里,
count($x)
将始终为您提供
1
。要获取
内容
元素的数量,需要对
$x
隐式根节点的子节点进行计数:
计数($x/content)

根据经验,您可以记住:如果
xsl:variable
本身是一个带有
select
属性的空元素,那么结果集将被分配给变量。如果使用
xsl:variable
而不使用
select
属性,则始终使用该变量创建一个隐式父级,并且该变量的内容是它下面的子级

这同样适用于将
xsl:sequence
作为
xsl:variable
的子对象的示例。通过使用非空的
xsl:variable
可以为序列创建一个隐式父级,这就是为什么如果计算变量本身,总是得到
1

如果您同时需要:
xsl:variable
中的一组语句,但是
select
属性的行为,则可以使用以下方法解决此问题:

<xsl:variable name="x">
    <content />
    <content />
</xsl:variable>
<xsl:variable name="x" select="$y/*" />

<xsl:variable name="y">
    <xsl:sequence select="foo" />
</xsl:variable>


这将产生
count($x)
的预期金额,但这是否真的有益或使代码更清晰是有争议的。

如果将变量声明更改为:

<xsl:variable name="seq" select="*"/>

谢谢你的回答。但我不确定我是否理解。。。my
seq
变量中究竟存储了什么(例如,当从samle输入处理时)。我以为这是两个
1
元素的序列。非常感谢!为了便于参考,这里是文档相关部分的链接(如果我理解正确的话):是的,您确实理解正确。规范的这一部分显示您隐式地拥有一条
xsl:document
指令。它还指出了我没有提到的其他内容:如果需要特定的输出类型,可以使用
as
属性。
xsl:variable
中的序列必须可转换为此类型,否则会发生错误。感谢您提供
item()*
explain
提示(是的,我使用saxon)。
<xsl:variable name="x" select="$y/*" />

<xsl:variable name="y">
    <xsl:sequence select="foo" />
</xsl:variable>
<xsl:variable name="seq" select="*"/>
<xsl:variable name="seq" as="item()*">
        <xsl:sequence select="*" />
</xsl:variable>
    <xsl:template match="sub" saxon:explain="yes" xmlns:saxon="http://saxon.sf.net/">
    <xsl:variable name="seq">
        <xsl:sequence select="*" />
    </xsl:variable>

    <xsl:message>
        <xsl:value-of select="@id" />
        <xsl:text>: </xsl:text>
        <xsl:value-of select="count($seq)" />
    </xsl:message>
</xsl:template>
Optimized expression tree for template at line 6 in :
                    let $seq[refCount=1] as document-node() :=
                      document-constructor
                        child::element()
                    return
                      message