如何连接两个节点集以尊重顺序?
我的理解是,尽管 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>
所以“|”运算符实际上不尊重节点集操作数的顺序。有没有办法可以连接节点集以尊重顺序?
My understanding has been that, despite the fact that XSLT's "node-sets" are called "sets", they are, in fact, ordered lists of nodes (which is why each node is associated with an index). I've therefore been trying to use the "|" operator to concatenate node-sets such that the order of the nodes is respected.
What I am attempting to accomplish is something like the following JavaScript code:
[o1,o2,o3].concat([o4,o5,o6])
Which yields:
[o1,o2,o3,o4,o5,o6]
But, consider the following reduced example:
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>
Given the following input:
<?xml version="1.0"?>
<root>
<element id="parentTransition"/>
<element id="childTransition"/>
</root>
Which yields (with xsltproc):
<?xml version="1.0"?>
<return>
<parentThenChildTransitions>
<element id="parentTransition"/><element id="childTransition"/>
</parentThenChildTransitions>
<childThenParentTransitions>
<element id="parentTransition"/><element id="childTransition"/>
</childThenParentTransitions>
</return>
So the "|" operator in fact does not respect the order of the node-set operands. Is there a way I can concatenate node-sets such that order is respected?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这实际上不是一个 XSLT,而是一个 XPath 问题。
在 XPath 1.0 中,没有任何类似于“列表”数据类型的内容。节点集是一个集合,它没有顺序。
在 XPath 2.0 中,有序列数据类型。序列中的任何项目都是有序的。这与文档顺序无关。此外,相同的项目(或节点)可以在序列中出现多次。
因此,在 XSLT 2.0 中,只需使用 XPath 2.0 序列连接运算符
,
:,这将计算出文档中具有
id
属性'parentTransition'
后跟文档中具有id
属性'childTransition'
的所有元素在 XSLT 中仍然可以访问并处理不按文档顺序的节点:例如使用
指令 - 然而,作为的结果处理的节点集: apply-templates>
或
是一个node-list
——而不是节点集。评估不按文档顺序的节点的另一个示例是
或< 中的
具有position()
函数;xsl:for-each>
子项或在(XPath 表达式的)定位步骤的谓词内,其中使用反向轴 (例如ancesstor::
或preceeding::
)This is actually not an XSLT but an XPath question.
In XPath 1.0 there isn't anything similar to a "list" datatype. A node-set is a set and it has no order.
In XPath 2.0 there is the sequence data type. Any items in a sequence are ordered. This has nothing to do with document order. Also, the same item (or node) can appear more than once in a sequence.
So, in XSLT 2.0 one just uses the XPath 2.0 sequence concatenation operator
,
:and this evaluates to the sequence of all elements in the document with
id
attribute'parentTransition'
followed by all elements in the document withid
attribute'childTransition'
In XSLT it is still possible to access and process nodes not in document order: for example using the
<xsl:sort>
instruction -- however the set of nodes that are processed as result of<xsl:apply-templates>
or<xsl:for-each>
is anode-list
-- not a node-set.Another example of evaluating nodes not in document order is the
position()
function within<xsl:apply-templates>
or<xsl:for-each>
that have a<xsl:sort>
child or within a predicate of a location step (of an XPath expression) in which a reverse axis is used (such asancesstor::
orpreceeding::
)在 XSLT 1.0 中,您可以按选定的顺序处理节点(例如使用 xsl:sort),但不能在变量中保存节点列表。您可以在变量中保存(或传递给模板等)的唯一内容是节点集;节点集没有内在顺序,但是当您处理它们时,它们始终按文档顺序处理,除非您使用 xsl:sort 请求不同的处理顺序。
您也许可以通过复制节点来解决您的问题:
但这取决于您的用例。
如果可以的话,切换到 XSLT 2.0!
In XSLT 1.0, you can process nodes in a selected order (for example by use of xsl:sort), but you can't hold a list of nodes in a variable. The only thing you can hold in a variable (or pass to a template, etc) is a node-set; node-sets have no intrinsic order, but when you process them, they are always processed in document order unless you use xsl:sort to request a different processing order.
You might be able to solve your problem by copying the nodes:
but this depends on your use-case.
Switch to XSLT 2.0 if you can!
“|”运算符将按文档顺序保留节点。在 XSLT 1.0 中,您需要进行连续的
copy
或for-each
操作。The "|" operator will retain nodes in document order. In XSLT 1.0 you will need to have sequential
copy
orfor-each
operations.