我不明白这个样式表的输出:
<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>
应用于以下XML时:
<root>
<sub id="empty" />
<sub id="one"><one/></sub>
<sub id="two"><one/><one/></sub>
<sub id="three"><one/><one/><one/></sub>
</root>
由xsl:message
元素编写的输出是:
empty: 1
one: 1
two: 1
three: 1
我期待这一个:
empty: 0
one: 1
two: 2
three: 3
为什么count($seq)
在这种情况下总是返回1?你如何改变变量定义,以便我以后可以测试它是否空虚? (简单<xsl:variable name='seq' select='*' />
会返回预期答案,但不是一个选项...我想在this template中更改between
变量,并稍后对其进行空虚测试。
答案 0 :(得分:5)
让我试着回答你问题的“为什么”部分。
如果你写下面的陈述:
<xsl:variable name="x" select="*" />
变量$x
包含当前节点的子节点的序列。 $x
中没有隐式父节点,因为您使用select
。现在考虑以下内容:
<xsl:variable name="x">
<content />
<content />
</xsl:variable>
其中变量$x
包含一个节点的序列:content
的父节点。在此,count($x)
将始终为您提供1
。要获取content
元素的数量,您需要计算$x
隐式根节点的子节点:count($x/content)
。
根据经验,您可以记住:如果xsl:variable
本身是具有select
属性的空元素,则结果集将分配给变量。如果使用不带xsl:variable
属性的select
,则始终使用变量创建隐式父级,并且变量的内容是其下的子级。
同样适用于xsl:sequence
作为xsl:variable
的孩子的示例。通过使用非空xsl:variable
,您可以为序列创建隐式父级,这就是为什么如果您自己计算变量,总是会得到1
。
如果您同时需要:xsl:variable
内的一组语句,但select
属性的行为,您可以使用以下方法解决此问题:
<xsl:variable name="x" select="$y/*" />
<xsl:variable name="y">
<xsl:sequence select="foo" />
</xsl:variable>
现在会产生count($x)
的预期金额,但这是否真的有益或使您的代码更清晰是有争议的。
答案 1 :(得分:3)
如果您将变量声明更改为:
,它可以正常工作<xsl:variable name="seq" select="*"/>
或使用'as'属性声明变量的类型:
<xsl:variable name="seq" as="item()*">
<xsl:sequence select="*" />
</xsl:variable>
在XSLT 2.0中,不指定任何类型信息通常会导致令人惊讶的结果。如果您使用的是Saxon,则可以使用explain扩展属性输出Saxon如何解释样式表:
<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>
如您所见,Saxon构建了一个文档节点:
Optimized expression tree for template at line 6 in :
let $seq[refCount=1] as document-node() :=
document-constructor
child::element()
return
message
答案 2 :(得分:2)
您正在选择子节点,然后计算每个节点 - 因此它始终为1.您需要计算子节点,例如:
<xsl:value-of select="count($seq/*)" />
会为您提供您期望的输出。