我的理解是,尽管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>
所以“|”实际上,运算符不遵循节点集操作数的顺序。有没有一种方法可以连接节点集,以便顺序得到尊重?
答案 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-list
或position()
中<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中,您需要执行顺序copy
或for-each
操作。
<xsl:copy-of select="$parentTransition"/>
<xsl:copy-of select="$childTransition"/>