XSLT xsl:序列.它对……有什么好处?



我知道下面的问题对初学者来说有点难,但我需要你的帮助来理解一个基本的概念。

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

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

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

我从来没有必要使用xsl:sequence。如果有人能给我一个xsl:sequence使用的例子,我将不胜感激,如果没有我上面提到的那些,我将首选或无法实现。

还有一件事,我当然读过xsl:sequence的定义,但我不能推断它是如何有用的。

<xsl:sequence>对原子值(或原子值序列)的操作与<xsl:copy-of>相同,都只是返回其输入的副本。当您考虑节点时,差异就出现了。

如果$n是单个元素节点,例如由

定义
<xsl:variable name="n" select="/html"/>
然后

<xsl:copy-of select="$n"/>

返回节点的副本,它具有相同的名称和子结构,但它是一个具有新标识(没有父)的节点。

<xsl:sequence select="$n"/>

返回节点$n,返回的节点与$n具有相同的父节点,并且通过is Xpath运算符与$n相等。

在传统的(XSLT 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:sequencexsl:copy-of的结果是完全不同的。

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>

这里的关键是它返回对原始节点的引用,它不生成新的副本。

为了返回某种类型的值,您使用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的新的基于模式的类型系统,需要一种方法来返回或传递这些类型的值,并且需要一个新的结构。

[edit]Michael Kay在他关于xsl:sequence的"XSLT 2.0和XPath 2.0程序员参考"中说:"XSLT 2.0中引入的这个看似无害的指令对XSLT语言的功能有深远的影响,因为它意味着XSLT指令和序列构造函数(以及函数和模板)能够返回XPath数据模型允许的任何值。没有它,XSLT指令只能用于在结果树中创建新节点,但是有了它,它们还可以返回原子值和对现有节点的引用。

另一种用法是仅在有子标记时创建标记。需要一个示例:

<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()是"是否有子元素?"的习语,引擎可以对其进行优化。

相关内容

  • 没有找到相关文章

最新更新