XSLT xsl:序列。到底有什么好处呢..?

时间:2013-01-16 15:16:11

标签: xslt xslt-1.0 xslt-2.0

我知道以下问题是一些初学者,但我需要你帮助才能理解一个基本概念。

首先我想说我是一名XSLT程序员已经3年了但是我在这里学到了一些新的和相当基础的东西我从来不知道(在我的工作中,任何人都学会了如何单独编程,那里没有涉及课程。)

我的问题是: xsl:sequence的用法是什么?

我一直在使用xsl:copy-of来按原样复制节点xsl:apply-templates,以便修改我选择的节点,并value-of用于简单文本。

我从来没有必要使用xsl:sequence。如果有人可以向我展示xsl:sequence使用的例子,我会很感激,如果没有我上面提到的那些,这是优先考虑或无法实现的。

还有一件事,我已经读过关于xsl:sequence定义的课程,但我无法推断它是如何有用的。

4 个答案:

答案 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()是“是否存在子元素?”的惯用语,引擎可以对其进行优化。这样做可以减轻每个人的生活。