我试图改变这种XML:
<!--- potential other elements before-->
<li>bla</li>
<li>bli</li>
<li>blo</li>
<anytag/>
<li>pla</li>
<li>pli</li>
<li>plo</li>
成:
<!--- potential other elements before-->
<ul>
<li>bla</li>
<li>bli</li>
<li>blo</li>
</ul>
<anytag/>
<ul>
<li>pla</li>
<li>pli</li>
<li>plo</li>
</ul>
所以基本上,选择所有兄弟姐妹<li>
,其中没有任何其他元素。
我正在使用XSLT 2.0。
所以我想做的事情如下:
<xsl:template match="li[1]">
<ul>
<li>
<xsl:value-of select="." />
</li>
<xsl:apply-templates select="following-sibling::li[preceding-sibling::node()][1]" mode="add-to-ul"/>
</ul>
</xsl:template>
<xsl:template match="li" mode="add-to-ul">
<li>
<xsl:value-of select="." />
</li>
</xsl:template>
<xsl:template match="li">
</xsl:template>
首先,这看起来并不太优雅,但是由于li [1]如果我有几个列表,它就会失败,显然是不行的。
有什么想法吗?
答案 0 :(得分:3)
在XSLT 2.0中,您可以使用xsl:for-each-group
指令轻松分组。
例如:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="root">
<root>
<xsl:for-each-group select="*" group-adjacent="boolean(self::li)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<ul>
<xsl:copy-of select="current-group()"/>
</ul>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
请注意,这需要从父节点的上下文中调用(在您的示例中未显示)。
答案 1 :(得分:3)
以下是纯XSLT 1.0解决方案(更短更简单)可以在任何浏览器中执行:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kGroup" match="li"
use="generate-id(preceding-sibling::*[not(self::li)][1])"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="li[not(preceding-sibling::*[1][self::li])]">
<ul>
<xsl:copy-of select="key('kGroup', generate-id(preceding-sibling::*[1]))"/>
</ul>
</xsl:template>
<xsl:template match="li"/>
</xsl:stylesheet>
将此转换应用于以下XML文档:
<t>
<a/>
<b/>
<li>bla</li>
<li>bli</li>
<li>blo</li>
<anytag/>
<li>pla</li>
<li>pli</li>
<li>plo</li>
<c/>
</t>
产生了想要的正确结果:
<t>
<a/>
<b/>
<ul>
<li>bla</li>
<li>bli</li>
<li>blo</li>
</ul>
<anytag/>
<ul>
<li>pla</li>
<li>pli</li>
<li>plo</li>
</ul>
<c/>
</t>
第二部分。处理多级嵌套列表
对转型进行一点调整:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kGroup" match="li"
use="concat(generate-id(..), generate-id(preceding-sibling::*[not(self::li)][1]))"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="li[not(preceding-sibling::*[1][self::li])]">
<ul>
<xsl:apply-templates mode="li" select=
". | key('kGroup', concat(generate-id(..),
generate-id(preceding-sibling::*[not(self::li)][1]))
)
[position() >1]"/>
</ul>
</xsl:template>
<xsl:template match="*" mode="li">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="li"/>
</xsl:stylesheet>
允许我们正确处理多个深度的嵌套列表,例如:
<t>
<a/>
<b/>
<li>bla</li>
<li>bli
<a>
<li>gla</li>
<li>gli</li>
<d>
<li>glo</li>
</d>
</a>
</li>
<li>blo</li>
<anytag/>
<li>pla</li>
<li>pli</li>
<li>plo</li>
<c/>
</t>
并生成想要的正确结果:
<t>
<a/>
<b/>
<ul>
<li>bla</li>
<li>bli
<a>
<ul>
<li>gla</li>
<li>gli</li>
</ul>
<d>
<ul>
<li>glo</li>
</ul>
</d>
</a>
</li>
<li>blo</li>
</ul>
<anytag/>
<ul>
<li>pla</li>
<li>pli</li>
<li>plo</li>
</ul>
<c/>
</t>