如何连接两个节点集以尊重顺序?

发布于 2024-10-10 10:01:33 字数 1922 浏览 0 评论 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>

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

可是我不能没有你 2024-10-17 10:01:33

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

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

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

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

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

,这将计算出文档中具有 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 ,:

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

and this evaluates to the sequence of all elements in the document with id attribute 'parentTransition' followed by all elements in the document with id 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 a node-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 as ancesstor:: or preceeding::)

╭⌒浅淡时光〆 2024-10-17 10:01:33

在 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!

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:

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

but this depends on your use-case.

Switch to XSLT 2.0 if you can!

伏妖词 2024-10-17 10:01:33

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

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

The "|" operator will retain nodes in document order. In XSLT 1.0 you will need to have sequential copy or for-each operations.

<xsl:copy-of select="$parentTransition"/>
<xsl:copy-of select="$childTransition"/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文