我知道以下问题是一些初学者,但我需要你帮助才能理解一个基本概念。
首先我想说我是一名XSLT程序员已经3年了但是我在这里学到了一些新的和相当基础的东西我从来不知道(在我的工作中,任何人都学会了如何单独编程,那里没有涉及课程。)
我的问题是:
xsl:sequence
的用法是什么?
我一直在使用xsl:copy-of
来按原样复制节点xsl:apply-templates
,以便修改我选择的节点,并value-of
用于简单文本。
我从来没有必要使用xsl:sequence
。如果有人可以向我展示xsl:sequence
使用的例子,我会很感激,如果没有我上面提到的那些,这是优先考虑或无法实现的。
还有一件事,我已经读过关于xsl:sequence
定义的课程,但我无法推断它是如何有用的。
答案 0 :(得分:40)
<xsl:sequence>
与<xsl:copy-of>
相同,只返回其输入的副本。考虑节点时会出现差异。
如果$ n是单个元素节点,例如由
之类的定义<xsl:variable name="n" select="/html"/>
然后
<xsl:copy-of select="$n"/>
返回节点的副本,它具有相同的名称和子结构,但它是一个带有新标识的 new 节点(并且没有父节点)。
<xsl:sequence select="$n"/>
返回节点$ n,返回的节点与$ n具有相同的父节点,并且由is
Xpath运算符等于它。
差异在传统(XSLT 1样式)模板用法中几乎完全被掩盖,因为您永远无法访问任一操作的结果,构造函数的结果是隐式复制到输出树,因此<{1}}不制作副本的事实被掩盖了。
xsl:sequence
与
相同<xsl:template match="a">
<x>
<xsl:sequence select="$n"/>
</x>
</xsl:template>
两者都创建一个新的元素节点,复制内容的结果作为新节点<xsl:template match="a">
<x>
<xsl:copy-of select="$n"/>
</x>
</xsl:template>
的子节点。
但是,如果使用函数,很快就会出现差异。
x
可生产
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="data:,f">
<xsl:variable name="s">
<x>hello</x>
</xsl:variable>
<xsl:template name="main">
::
:: <xsl:value-of select="$s/x is f:s($s/x)"/>
:: <xsl:value-of select="$s/x is f:c($s/x)"/>
::
:: <xsl:value-of select="count(f:s($s/x)/..)"/>
:: <xsl:value-of select="count(f:c($s/x)/..)"/>
::
</xsl:template>
<xsl:function name="f:s">
<xsl:param name="x"/>
<xsl:sequence select="$x"/>
</xsl:function>
<xsl:function name="f:c">
<xsl:param name="x"/>
<xsl:copy-of select="$x"/>
</xsl:function>
</xsl:stylesheet>
此处$ saxon9 -it main seq.xsl
<?xml version="1.0" encoding="UTF-8"?>
::
:: true
:: false
::
:: 1
:: 0
::
和xsl:sequence
的结果完全不同。
答案 1 :(得分:23)
xsl:sequence最常见的用例是从xsl:function返回结果。
<xsl:function name="f:get-customers">
<xsl:sequence select="$input-doc//customer"/>
</xsl:function>
但它在其他情况下也可以派上用场,例如
<xsl:variable name="x" as="element()*">
<xsl:choose>
<xsl:when test="$something">
<xsl:sequence select="//customer"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="//supplier"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
这里的关键是它返回对原始节点的引用,它不会创建新副本。
答案 2 :(得分:6)
为了返回某个类型的值,您使用xsl:sequence
作为xsl:value-of
,尽管它的名称始终创建一个文本节点(因为XSLT 1.0)。
所以在函数体中使用
<xsl:sequence select="42"/>
要返回xs:integer
值,您可以使用
<xsl:sequence select="'foo'"/>
返回xs:string
值和
<xsl:sequence select="xs:date('2013-01-16')"/>
返回xs:date
值,依此类推。当然你也可以用例如<xsl:sequence select="1, 2, 3"/>
。
在我的视图中,您不希望在这些情况下创建文本节点甚至元素节点,因为它效率低下。
所以这是我的看法,使用基于XSLT和XPath 2.0的新的基于模式的类型系统,需要一种方法来返回或传递这些类型的值,并且需要一个新的构造。
[编辑]迈克尔凯在他的“XSLT 2.0和XPath 2.0程序员参考”中谈到xsl:sequence
:“XSLT 2.0中引入的这种无辜的指令对XSLT语言的功能有着深远的影响,因为它意味着XSLT指令和序列构造函数(以及函数和模板)能够返回XPath数据模型允许的任何值。没有它,XSLT指令只能用于在结果树中创建新节点,但是使用它,它们也可以返回原子值和对现有节点的引用。“
答案 3 :(得分:0)
另一个用途是仅在有标记的情况下创建标记。需要一个例子:
<a>
<b>node b</b>
<c>node c</c>
</a>
XSLT中的某个地方:
<xsl:variable name="foo">
<xsl:if select="b"><d>Got a "b" node</d></xsl:if>
<xsl:if select="c"><d>Got a "c" node</d></xsl:if>
</xsl:variable>
<xsl:if test="$foo/node()">
<wrapper><xsl:sequence select="$foo"/></wrapper>
</xsl:if>
您可以在此处看到演示:http://xsltransform.net/eiZQaFz
这比测试每个标签更好:
<xsl:if test="a|b">...</xsl:if>
因为你最终会在两个地方编辑它。处理速度也取决于您的输入中的标签。如果它是您测试中的最后一个,则引擎将测试之前是否存在。由于$ foo / node()是“是否存在子元素?”的惯用语,引擎可以对其进行优化。这样做可以减轻每个人的生活。