如何连接两个节点集以使订单得到尊重?

时间:2011-01-06 01:15:09

标签: xslt xpath xpath-2.0

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

我想要完成的是类似下面的JavaScript代码:

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

哪个收益率:

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

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

testFlatten.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>

所以“|”实际上,运算符不遵循节点集操作数的顺序。有没有一种方法可以连接节点集,以便顺序得到尊重?

3 个答案:

答案 0 :(得分:8)

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

在XPath 1.0中,没有任何类似于“list”数据类型的东西。节点集是一个集合,没有订单。

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

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

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

这将评估文档中包含id属性'parentTransition'的所有元素的序列,后跟文档中id属性'childTransition'

的所有元素

在XSLT中,仍然可以访问和处理非文档顺序的节点:例如,使用<xsl:sort>指令 - 但是由于{的结果处理的节点集{1}}或<xsl:apply-templates><xsl:for-each> - 不是节点集。

评估不符合文档顺序的节点的另一个示例node-listposition()<xsl:apply-templates><xsl:for-each>子函数使用反向轴的位置步骤(XPath表达式)的谓词(例如<xsl:sort>ancesstor::

答案 1 :(得分: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!

答案 2 :(得分:1)

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

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