为什么没有兄弟轴?

时间:2013-11-02 09:54:35

标签: xslt

查看XSLT中的可用轴,我必须发现没有sibling轴,它将是preceding-siblingfollowing-sibling的并集。对我来说这有点令人惊讶,因为我已经写了一个答案(XSLT issue...CSV issue.?),其中这个轴会有所帮助(尽管到目前为止我只有大约10个答案)。当然,显而易见的是,您始终可以使用union来解决问题。所以这个轴并不是真正需要的。但它偶尔会非常方便,并且像所有其他轴一样,它会使代码更易读,更容易维护。

有人知道为什么这个轴被遗漏了吗?可能有一个非明显的原因吗?

顺便说一句:我在StackExchange上发现了至少一个问题,并警告使用preceding-siblingfollowing-sibling轴可能会降低性能。但我认为对于包含大部分XML树的所有轴都是以嵌套方式使用的情况。所以遗漏的原因不一定是因为表现。

1 个答案:

答案 0 :(得分:2)

由于此问题暂时没有活动,我想自己回答。在评论中提出一个想法,当然很难回顾性地说明为什么负责XSLT 1.0规范的人省略了sibling轴。

其中一个最确凿的原因可能与@JLRiche和@MichaelKay的评论有关:轴应该进入与参考节点相关的特定方向,可能很难确定{的方向是什么{1}}将是。

为了进一步研究这个问题,我设置了一个测试XSLT和一个测试输入XML来检查轴的工作方式(详见下文),特别是节点的 order 。轴是。结果让我感到惊讶:

  • sibling从最靠近参考节点的节点开始,但节点最接近文档的开头。
  • preceding-sibling 从参考节点开始。

这实际上允许定义

following-sibling

此集合中的节点从文档的开头到结尾不断迭代。没有“跳跃”。

建议的备选方案

sibling := preceding-sibling | following-sibling

也可以正常工作并以相同的顺序生成相同的集合。但是,看一个不熟悉的XSLT,我会假设../node except . 轴比使用parent-children结构更能解释逻辑。

有趣的是,轴不是最靠近参考节点但最接近文档开头的节点处开始的事实也适用于siblingpreceding,例如{{1不返回节点的父节点而是返回根节点。

我提出这个问题的最初动机是不必重复对节点的属性施加冗长的ancestor,例如我不想写

ancester::node[1]

但是,由于上面的表达式可以改写为

CONDITION

必须使用两个轴而不是preceding-sibling::node[CONDITION] | following-sibling::node[CONDITION] 轴的缺点并不像想象的那么糟糕。当然,在XSLT 2.0中,这也适用于

(preceding-sibling::node | following-sibling::node)[CONDITION]

所以,回答我的问题:我认为没有充分的理由不定义sibling轴。我想没有人想到它。 : - )

测试设置

此XML测试输入

(../node except .)[CONDITION]

使用此XSLT 2.0表

sibling

将产生此输出

<?xml version="1.0" encoding="ISO-8859-1"?>
<node id="1">
  <node id="2">
    <node id="3">
      <node id="4"/>
      <node id="5"/>
      <node id="6"/>
    </node>
    <node id="7">
      <node id="8"/>
      <node id="9"/>
      <node id="10"/>
    </node>
    <node id="11">
      <node id="12"/>
      <node id="13"/>
      <node id="14"/>
    </node>
  </node>    
  <node id="15">
    <node id="16">
      <node id="17"/>
      <node id="18"/>
      <node id="19"/>
    </node>
    <node id="20">
      <node id="21"/>
      <node id="22"/>
      <node id="23"/>
    </node>
    <node id="24">
      <node id="25"/>
      <node id="26"/>
      <node id="27"/>
    </node>
  </node>
  <node id="28">
    <node id="29">
      <node id="30"/>
      <node id="31"/>
      <node id="32"/>
    </node>
    <node id="33" value="A">
      <node id="34"/>
      <node id="35"/>
      <node id="36"/>
    </node>
    <node id="37">
      <node id="38"/>
      <node id="39"/>
      <node id="40"/>
    </node>
    <node id="41">
      <node id="42"/>
      <node id="43"/>
      <node id="44"/>
    </node>
    <node id="45" value="A">
      <node id="46"/>
      <node id="47"/>
      <node id="48"/>
    </node>
  </node>
</node>