使用XSLT / XPATH 1.0,我想创建一个HTML,其中class
元素的span
属性表示原始XML层次结构中的深度。
例如,使用此XML片段:
<text>
<div type="Book" n="3">
<div type="Chapter" n="6">
<div type="Verse" n="12">
</div>
</div>
</div>
</text>
我想要这个HTML:
<span class="level1">Book 3</span>
<span class="level2">Chapter 6</span>
<span class="level3">Verse 12</span>
这些div
元素的深度不是先验的。 div
可以是Book - &gt;章节。它们可能是音量 - &gt;书 - &gt;章 - &gt;段落 - &gt;线。
我不能依赖@type的值。部分或全部可能为NULL。
答案 0 :(得分:17)
这有一个非常简单和简短的解决方案 - 没有递归,没有参数,没有xsl:element
,没有xsl:attribute
:
<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:template match="div">
<span class="level{count(ancestor::*)}">
<xsl:value-of select="concat(@type, ' ', @n)"/>
</span>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<text>
<div type="Book" n="3">
<div type="Chapter" n="6">
<div type="Verse" n="12"></div></div></div>
</text>
产生了想要的正确结果:
<span class="level1">Book 3</span>
<span class="level2">Chapter 6</span>
<span class="level3">Verse 12</span>
解释:正确使用模板,AVT和count()
功能。
答案 1 :(得分:5)
或者不使用递归 - 但Dimitre的回答比我的回答要好。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/text">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="//div">
<xsl:variable name="depth" select="count(ancestor::*)"/>
<xsl:if test="$depth > 0">
<xsl:element name="span">
<xsl:attribute name="class">
<xsl:value-of select="concat('level',$depth)"/>
</xsl:attribute>
<xsl:value-of select="concat(@type, ' ' , @n)"/>
</xsl:element>
</xsl:if>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:0)
与XSL一样,使用递归。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/text">
<html>
<xsl:apply-templates>
<xsl:with-param name="level" select="1"/>
</xsl:apply-templates>
</html>
</xsl:template>
<xsl:template match="div">
<xsl:param name="level"/>
<span class="{concat('level',$level)}"><xsl:value-of select="@type"/> <xsl:value-of select="@n"/></span>
<xsl:apply-templates>
<xsl:with-param name="level" select="$level+1"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>