我正在使用XSLT进行xml到html的转换,
我的输入xml文件如下所示,
<doc>
<h1>main header 1-1</h1>
<p>para 1</p>
<p>para 2</p>
<h1>main header 1-2</h1>
<p>para 3</p>
<p>para 4</p>
<h2>sub header 2-1</h2>
<p>para 5</p>
<p>para 6</p>
<p>para 7</p>
<h2>sub header 2-3</h2>
<p>para 8</p>
<p>para 9</p>
<h1>main header 1-3</h1>
<p>para 10</p>
<h2>sub header 2-3</h2>
<p>para 11</p>
<p>para 12</p>
</doc>
我在xml文件中的预期输出如下所示
<doc>
<div id="h1-1">
<h1>main header 1-1</h1>
<p>para 1</p>
<p>para 2</p>
</div>
<div id="h1-2">
<h1>main header 1-2</h1>
<p>para 3</p>
<p>para 4</p>
</div>
<div id="h2-1">
<h2>sub header 2-1</h2>
<p>para 5</p>
<p>para 6</p>
<p>para 7</p>
</div>
<div id="h2-2">
<h2>sub header 2-3</h2>
<p>para 8</p>
<p>para 9</p>
</div>
<div id="h1-3">
<h1>main header 1-3</h1>
<p>para 10</p>
</div>
<div id="h2-3">
<h2>sub header 2-3</h2>
<p>para 11</p>
<p>para 12</p>
</div>
</doc>
我有跟随xsl来完成这项任务,
<xsl:function name="san:group-div" as="element()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$elements" group-starting-with="*[local-name() eq concat('h', $level)]">
<xsl:choose>
<xsl:when test="self::*[local-name() eq concat('h', $level)]">
<div id="{local-name()}-{count(preceding-sibling::*[local-name() eq local-name(current())]) + 1}">
<xsl:apply-templates select="current-group()"/>
</div>
<xsl:sequence select="san:group-div(current-group() except ., $level + 1)"/>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="doc">
<xsl:copy>
<xsl:sequence select="san:group-div(*, 1)"/>
</xsl:copy>
</xsl:template>
然而它给了我以下结果。
<doc>
<div id="h1-1">
<h1>main header 1-1</h1>
<p>para 1</p>
<p>para 2</p>
</div>
<div id="h1-2">
<h1>main header 1-2</h1>
<p>para 3</p>
<p>para 4</p>
<h2>sub header 2-1</h2>
<p>para 5</p>
<p>para 6</p>
<p>para 7</p>
<h2>sub header 2-3</h2>
<p>para 8</p>
<p>para 9</p>
</div>
<div id="h2-1">
<h2>sub header 2-1</h2>
<p>para 5</p>
<p>para 6</p>
<p>para 7</p>
</div>
<div id="h2-2">
<h2>sub header 2-3</h2>
<p>para 8</p>
<p>para 9</p>
</div>
<div id="h1-3">
<h1>main header 1-3</h1>
<p>para 10</p>
<h2>sub header 2-3</h2>
<p>para 11</p>
<p>para 12</p>
</div>
<div id="h2-3">
<h2>sub header 2-3</h2>
<p>para 11</p>
<p>para 12</p>
</div>
</doc>
如结果所示,<h2>
个节点也会被复制到<h1>
div
。 (请参阅<div id="h1-2">
和<div id="h1-3">
)。
任何人都可以建议我如何安排我的代码来获得预期的输出?
答案 0 :(得分:2)
怎么样......
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="html" version="5.0" indent="yes" encoding="utf-8" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<html>
<head>
<title>Doc</title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="doc">
<doc>
<xsl:for-each-group select="h1|h2|h3|p" group-adjacent="
if (self::p)
then
(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3)[last()]/local-name()
else
local-name()">
<xsl:for-each-group select="current-group()" group-starting-with="h1|h2|h3">
<div id="{local-name()}-{position()}">
<xsl:copy-of select="current-group()" />
</div>
</xsl:for-each-group>
</xsl:for-each-group>
</doc>
</xsl:template>
</xsl:stylesheet>
这假设您的标题级别仅限于h1
,h2
和h3
。如果没有,根据需要进行调整是一项微不足道的工作。