假设我有以下 XML:
<?xml version="1.0" encoding="utf8"?>
<test>
<list>
<li>a</li>
<li>a</li>
<li begin="true">b</li> <!-- begin of the "b" list -->
<li>b</li>
<li>b</li>
<li end="true">b</li> <!-- end of the "b" list -->
<li>c</li>
<li>c</li>
</list>
</test>
我想使用 XSLT 1.0 根据begin
和end
属性将此列表拆分为三个列表,结果如下:
<list>
<li>a</li>
<li>a</li>
</list>
<list>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
</list>
<list>
<li>c</li>
<li>c</li>
</list>
我设法选择了第一个和第三个列表,但在匹配中间列表的范围时遇到了困难:
<xsl:template match="list">
<list>
<xsl:apply-templates select="li[@begin = 'true']/preceding-sibling::li" />
</list>
<list>
<xsl:apply-templates select="li[...]" /> <!-- Hmm 🤔 -->
</list>
<list>
<xsl:apply-templates select="li[@end = 'true']/following-sibling::li" />
</list>
</xsl:template>
position()
我尝试使用和进行各种表达,count()
但都不能完全正确。
附录:属性begin
和end
是唯一的,即原始列表中恰好有一个这样的组。
在给定的示例中,只有 1 个标记组(因此总共只有 3 个组),您可以使用:
(为了便于阅读,我将其分成了两个单独的说明。)
额外:
如果您正在使用libxslt处理器,您可以利用它支持的一些扩展功能并执行以下操作:
只要您声明:
在
xsl:stylesheet
开始标签中。此 xslt 返回预期结果
在一般情况下,使用 XSLT 1.0 会相当棘手,如果可以的话,最好转到 XSLT 2.0+,其中有类似的说明
xsl:for-each-group group-starting-with....
。很大程度上取决于问题的普遍性,例如,是否可以在一系列兄弟元素中拥有多个“开始”和“结束”,或者甚至可以嵌套开始和结束。(永远记住,一个例子并不能定义你的问题:我们需要了解问题的普遍性,而不是仅仅了解其中的一个例子。)
一个很有用的技巧(不仅在 1.0 中,在后续版本中也适用)是“兄弟递归”,即对第一个子节点执行 apply-templates 操作,然后对下一个子节点也执行 apply-templates 操作,以此类推。这里有一个例子:
XSLT 1.0 选择“标志”节点之间的所有节点
您可以通过搜索“XSLT 兄弟递归”找到其他内容。
您向我们展示的标记是“重叠标记”的一个例子,并且有大量关于这个主题的文献:如果您有很多这样的 XML,那么熟悉这个理论是值得的。
可以这样做: