如何使用XSLT从平面xml文件创建html列表
我正在寻找一种干净的方法来使用XSLT完成以下工作 转换此源:如何使用XSLT从平面xml文件创建html列表,xml,xslt,xpath,xslt-2.0,xslt-grouping,Xml,Xslt,Xpath,Xslt 2.0,Xslt Grouping,我正在寻找一种干净的方法来使用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</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>
废话
num1
num2
num3
废话
num1
num2
废话废话废话
对于此输出:
<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>
废话废话
到目前为止,我有:
<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>
废话废话
num1
num2
num3
废话
num1
num2
废话废话废话
我知道为什么我会得到重复的
元素,但我不知道如何阻止它。真是个脑筋急转弯
任何帮助都将不胜感激。这一转变:
<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>
<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>
<t>
<bara>blah blah</bara>
<ol>
<li>num1</li>
<li>num2</li>
<li>num3</li>
</ol>
<vara>blah blah</vara>
<ol>
<li>num1</li>
<li>num2</li>
</ol>
<dara>blah blah blah blah blah</dara>
</t>
将此转换应用于以下XML文档时(请注意,分隔元素现在具有随机名称):
废话
num1
num2
num3
废话
num1
num2
废话废话废话
生成所需的正确结果:
<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>
<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>
<t>
<bara>blah blah</bara>
<ol>
<li>num1</li>
<li>num2</li>
<li>num3</li>
</ol>
<vara>blah blah</vara>
<ol>
<li>num1</li>
<li>num2</li>
</ol>
<dara>blah blah blah blah blah</dara>
</t>
废话
num1
num2
num3
废话
num1
num2
废话废话废话
此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>
废话废话
编辑:压缩代码。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>
废话
num1
num2
num3
废话
num1
num2
废话废话废话
您将获得所需的输出:
<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>
废话废话
你应该在上阅读每个小组的许多重复内容:谢谢你的帮助,这是一种可能的方法。但这种方法不难维持吗?因为我必须在匹配的每个顶级元素上添加以下同级选择。@joe:此样式表有四个规则:默认细粒度遍历规则、
p
规则、ol
规则和li
规则。所以,这是一对一的转换。我看不出难以维护的问题。你已经要求Dimitre:如果列表前有一个元素H1呢。那么,您必须声明与H1
有什么关系。现在,它被绕过了。所以,有两种解决方案:复制您不想转换的所有内容,或者为H1
添加规则。我也必须加入比赛。@joe:是的,将模板应用于第一个孩子和第一个跟随的兄弟姐妹就是这样。谢谢!这看起来是一个很好的方法。但我认为使用这样的“砖块”模板规则是没有好处的。