好的家伙我认为这是一个棘手的问题......
我正在寻找一种使用XSLT执行以下操作的简洁方法:
转换此来源:
<para>blah blah</para>
<list>num1</list>
<list>num2</list>
<list>num3</list>
<para>blah blah</para>
<list>num1</list>
<list>num2</list>
<para>blah blah blah blah blah</para>
到此输出:
<p>blah blah</p>
<ol>
<li>num1</li>
<li>num2</li>
<li>num3</li>
</ol>
<p>blah blah</p>
<ol>
<li>num1</li>
<li>num2</li>
</ol>
<p>blah blah blah blah blah</p>
请记住,我不确切知道会有多少<list>
。
到目前为止,我有这个:
<xsl:template match="para">
<p><xsl:value-of select="." /></p>
</xsl:template>
<xsl:template match="list">
<ol><li><xsl:value-of select="." /></li></ol>
</xsl:template>
但我的输出看起来像这样:
<p>blah blah</p>
<ol><li>num1</li></ol>
<ol><li>num2</li></ol>
<ol><li>num3</li></ol>
<p>blah blah</p>
<ol><li>num1</li></ol>
<ol><li>num2</li></ol>
<p>blah blah blah blah blah</p>
我知道为什么我会收到重复的<ol>
元素,但我不知道如何阻止它。相当一个脑筋急转弯。
非常感谢任何帮助。
答案 0 :(得分:2)
这个XSLT 1.0样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()">
<xsl:apply-templates select="node()[1]|following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="para">
<p>
<xsl:value-of select="."/>
</p>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="list[preceding-sibling::node()[1][not(self::list)]]">
<ol>
<xsl:call-template name="makeList"/>
</ol>
<xsl:apply-templates select="following-sibling::node()
[not(self::list)][1]"/>
</xsl:template>
<xsl:template match="list" name="makeList">
<li>
<xsl:value-of select="."/>
</li>
<xsl:apply-templates select="following-sibling::node()[1]
[self::list]"/>
</xsl:template>
</xsl:stylesheet>
输出:
<p>blah blah</p>
<ol>
<li>num1</li>
<li>num2</li>
<li>num3</li>
</ol>
<p>blah blah</p>
<ol>
<li>num1</li>
<li>num2</li>
</ol>
<p>blah blah blah blah blah</p>
注意:细粒度遍历。
编辑:压缩代码。
答案 1 :(得分:1)
XSLT 2.0具有专门用于此类操作的工具:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="xml">
<xsl:for-each-group select="*" group-adjacent="boolean(self::list)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<ol>
<xsl:apply-templates select="current-group()"/>
</ol>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="para">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="list">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
</xsl:stylesheet>
使用此XML:
<xml>
<para>blah blah</para>
<list>num1</list>
<list>num2</list>
<list>num3</list>
<para>blah blah</para>
<list>num1</list>
<list>num2</list>
<para>blah blah blah blah blah</para>
</xml>
您将获得所需的输出:
<p>blah blah</p>
<ol>
<li>num1</li>
<li>num2</li>
<li>num3</li>
</ol>
<p>blah blah</p>
<ol>
<li>num1</li>
<li>num2</li>
</ol>
<p>blah blah blah blah blah</p>
上阅读for-each-group
答案 2 :(得分:0)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowing" match="list"
use="generate-id(preceding-sibling::para[1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="para">
<p>
<xsl:apply-templates/>
</p>
<xsl:variable name="vFol"
select="key('kFollowing',generate-id())"/>
<xsl:if test="$vFol">
<ol>
<xsl:apply-templates mode="copy"
select="key('kFollowing',generate-id())"/>
</ol>
</xsl:if>
</xsl:template>
<xsl:template match="list" mode="copy">
<li><xsl:value-of select="."/></li>
</xsl:template>
<xsl:template match="list"/>
</xsl:stylesheet>
应用于以下XML文档(将提供的输入包装在单个顶部元素中):
<t>
<para>blah blah</para>
<list>num1</list>
<list>num2</list>
<list>num3</list>
<para>blah blah</para>
<list>num1</list>
<list>num2</list>
<para>blah blah blah blah blah</para>
</t>
生成想要的正确结果:
<t>
<p>blah blah</p>
<ol>
<li>num1</li>
<li>num2</li>
<li>num3</li>
</ol>
<p>blah blah</p>
<ol>
<li>num1</li>
<li>num2</li>
</ol>
<p>blah blah blah blah blah</p>
</t>
更新:OP已在评论中指出现在他想要一个解决方案,其中任何非list
元素可以划分一组相邻的{{ 1}}兄弟姐妹。
以下是已更改问题的解决方案:
list
对以下XML文档应用此转换时(请注意,分隔元素现在具有随机名称):
<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="kFollowing" match="list"
use="generate-id(preceding-sibling::*[not(self::list)][1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(self::list) and following-sibling::*[1][self::list]]">
<xsl:call-template name="identity"/>
<xsl:variable name="vFol"
select="key('kFollowing',generate-id())"/>
<xsl:if test="$vFol">
<ol>
<xsl:apply-templates mode="copy"
select="key('kFollowing',generate-id())"/>
</ol>
</xsl:if>
</xsl:template>
<xsl:template match="list" mode="copy">
<li><xsl:value-of select="."/></li>
</xsl:template>
<xsl:template match="list"/>
</xsl:stylesheet>
产生了想要的正确结果:
<t>
<bara>blah blah</bara>
<list>num1</list>
<list>num2</list>
<list>num3</list>
<vara>blah blah</vara>
<list>num1</list>
<list>num2</list>
<dara>blah blah blah blah blah</dara>
</t>