综观XSLT我必须找出没有可用的轴sibling
轴这将是联盟preceding-sibling
及following-sibling
。 对我来说,这是一个令人感到有点惊讶,因为我已经写了一个答案( XSLT问题... CSV问题? ),其中该轴将是有帮助的(虽然我只有约10答案为止)。 当然,很明显,你可以随时通过工会解决问题。 所以这个轴是不是真的需要。 但它会在一段时间是非常方便的每一次,像所有其他轴恕我直言,这将使得代码更易读,更容易维护。
有谁知道为什么这个轴被排除在外? 是否有可能为这个非显而易见的原因是什么?
顺便说一句:我发现至少有一个问题上StackExchange了有关使用一个潜在的性能下降警告preceding-sibling
及following-sibling
轴。 但我相信在嵌套方式使用所有包含XML树的很大一部分轴这是真的。 因此,对于不作为的理由不能一直由于性能。
由于一直没有活动这个问题了,而我想回答它自己。 在评论中拿起一个念头,这是当然的,很难追溯说为什么负责XSLT 1.0规范的人省略了sibling
轴。
其中最确凿的原因可能已涉及到由@JLRiche和@MichaelKay评论:轴都应该进入一个特定的方向相对于参考节点,它可能是难以确定的方向是什么sibling
会。
为了研究这个远一点我建立了一个测试XSLT和测试输入XML检查轴是如何工作(见下文),特别是哪些节点在轴的顺序是。 结果是令人惊讶的对我说:
- 的
preceding-sibling
轴在节点最接近基准节点但最接近文档的开始节点不启动。 - 在
following-sibling
也开始在参考节点。
这实际上允许定义
sibling := preceding-sibling | following-sibling
在这组中的节点正在不断地从文件末尾的开头起反复。 就没有“跳”。
建议的替代方案
../node except .
也运作良好,并得到在同一顺序相同的一组。 然而,看着陌生的XSLT我会假设,一个sibling
轴可以解释比使用父子构建更好的逻辑。
有趣的是,事实上,轴不会在节点最接近基准节点开始,但在节点最接近文档的开头也适用于preceding
和ancestor
所以例如ancester::node[1]
不返回的父节点,但根节点。
我最初的动机要问的问题是有关不必重复漫长的CONDITION
强加给节点的属性,例如,我不想写
preceding-sibling::node[CONDITION] | following-sibling::node[CONDITION]
然而,由于上面的表达式可以改写为
(preceding-sibling::node | following-sibling::node)[CONDITION]
不必使用两个轴,而不是一个的的缺点sibling
轴不为思想那样糟糕。 当然,在XSLT 2.0,这也适用于
(../node except .)[CONDITION]
因此,要回答我的问题:我不认为这是一个很好的理由不定义sibling
轴。 我猜它没有人会想到。 :-)
测试设置
该XML测试输入
<?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>
使用该XSLT 2.0片
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:variable name="id" select="'37'"/>
<xsl:template name="dump">
<xsl:text> </xsl:text>
<xsl:value-of select="@id"/>
</xsl:template>
<xsl:template match="//node[@id = $id]">
<xsl:text>preceding siblings: </xsl:text>
<xsl:for-each select="preceding-sibling::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> following siblings: </xsl:text>
<xsl:for-each select="following-sibling::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> preceding and following siblings: </xsl:text>
<xsl:for-each select="preceding-sibling::node | following-sibling::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> preceding and following siblings with value A: </xsl:text>
<xsl:for-each select="(preceding-sibling::node | following-sibling::node)[@value = 'A']">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> following siblings: </xsl:text>
<xsl:for-each select="following-sibling::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> parent's children: </xsl:text>
<xsl:for-each select="../node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> parent's children except self: </xsl:text>
<xsl:for-each select="../node except .">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> parent's children except self with value A: </xsl:text>
<xsl:for-each select="(../node except .)[@value = 'A']">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> ancestors: </xsl:text>
<xsl:for-each select="ancestor::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> immediate ancestor: </xsl:text>
<xsl:for-each select="(ancestor::node)[1]">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> ancestors or self: </xsl:text>
<xsl:for-each select="ancestor-or-self::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> descendants: </xsl:text>
<xsl:for-each select="descendant::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> descendants or self: </xsl:text>
<xsl:for-each select="descendant-or-self::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> preceding: </xsl:text>
<xsl:for-each select="preceding::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
<xsl:text> following: </xsl:text>
<xsl:for-each select="following::node">
<xsl:call-template name="dump"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
会产生这种输出
preceding siblings: 29 33
following siblings: 41 45
preceding and following siblings: 29 33 41 45
preceding and following siblings with value A: 33 45
following siblings: 41 45
parent's children: 29 33 37 41 45
parent's children except self: 29 33 41 45
parent's children except self with value A: 33 45
ancestors: 1 28
immediate ancestor: 1
ancestors or self: 1 28 37
descendants: 38 39 40
descendants or self: 37 38 39 40
preceding: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 29 30 31 32 33 34 35 36
following: 41 42 43 44 45 46 47 48