4

我的理解是,尽管 XSLT 的“节点集”被称为“集”,但它们实际上是节点的有序列表(这就是每个节点与索引相关联的原因)。因此,我一直在尝试使用“|” 运算符连接节点集,以便遵守节点的顺序。

我试图完成的是类似于下面的 JavaScript 代码:

[o1,o2,o3].concat([o4,o5,o6])

产生:

[o1,o2,o3,o4,o5,o6]

但是,请考虑以下简化示例:

测试扁平化.xsl

<?xml version="1.0"?>
<xsl:stylesheet 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 version="1.0">
 <xsl:output method="xml"/>

 <xsl:template match="/">

  <xsl:variable name="parentTransition" select="//*[@id='parentTransition']"/>
  <xsl:variable name="childTransition" select="//*[@id='childTransition']"/>
  <xsl:variable name="parentThenChildTransitions" select="$parentTransition | $childTransition"/>
  <xsl:variable name="childThenParentTransitions" select="$childTransition | $parentTransition"/>

  <return>
   <parentThenChildTransitions>
    <xsl:copy-of select="$parentThenChildTransitions"/>
   </parentThenChildTransitions>
   <childThenParentTransitions>
    <xsl:copy-of select="$childThenParentTransitions"/>
   </childThenParentTransitions>
  </return>

 </xsl:template>

</xsl:stylesheet>

给定以下输入:

<?xml version="1.0"?>
<root>
        <element id="parentTransition"/>

 <element id="childTransition"/>
</root>

产生(使用xsltproc):

<?xml version="1.0"?>
<return>
    <parentThenChildTransitions>
        <element id="parentTransition"/><element id="childTransition"/>
    </parentThenChildTransitions>
    <childThenParentTransitions>
        <element id="parentTransition"/><element id="childTransition"/>
    </childThenParentTransitions>
</return>

所以“|” 运算符实际上不尊重节点集操作数的顺序。有没有办法可以连接节点集以尊重顺序?

4

3 回答 3

8

这实际上不是 XSLT 而是 XPath 问题。

在 XPath 1.0 中没有任何类似于“列表”数据类型的东西。节点集是一个集合,它没有顺序。

在 XPath 2.0 中有序列数据类型。序列中的任何项目都是有序的。这与文档顺序无关。此外,同一个项目(或节点)可以在一个序列中出现多次。

因此,在 XSLT 2.0 中,只需使用 XPath 2.0 序列连接运算符,

//*[@id='parentTransition'] , //*[@id='childTransition']

并且这将评估为具有属性的文档中所有元素的序列,然后是具有属性的文档中的所有id元素'parentTransition'id'childTransition'

在 XSLT 中,仍然可以访问和处理不按文档顺序的节点:例如使用<xsl:sort>指令——但是作为结果处理的节点集<xsl:apply-templates>或者<xsl:for-each>是一个node-list——而不是节点集。

另一个评估不按文档顺序的节点的示例是 在使用反向轴(例如或)的位置步骤(XPath 表达式的)的谓词内或具有子节点或谓词内的position()函数<xsl:apply-templates><xsl:for-each><xsl:sort>ancesstor::preceeding::

于 2011-01-06T01:52:20.087 回答
3

在 XSLT 1.0 中,您可以按选定的顺序处理节点(例如通过使用 xsl:sort),但不能在变量中保存节点列表。唯一可以保存在变量中(或传递给模板等)的是节点集;节点集没有内在顺序,但是当您处理它们时,它们总是按文档顺序处理,除非您使用 xsl:sort 请求不同的处理顺序。

您可以通过复制节点来解决您的问题:

<xsl:variable name="temp">
  <xsl:copy-of select="$ns0"/>
  <xsl:copy-of select="$ns1"/>
</xsl:variable>
...
<xsl:apply-templates select="exslt:node-set($temp/*)"/>

但这取决于您的用例。

如果可以,请切换到 XSLT 2.0!

于 2011-01-06T09:13:39.677 回答
1

“|” 运算符将按文档顺序保留节点。在 XSLT 1.0 中,您需要有顺序copyfor-each操作。

<xsl:copy-of select="$parentTransition"/>
<xsl:copy-of select="$childTransition"/>
于 2011-01-06T01:21:24.517 回答