XSLT - 使用 for-each-group 对以下兄弟姐妹进行分组
XSLT - grouping following siblings with for-each-group
我正在使用 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">
)。
任何人都可以建议我如何安排我的代码以获得预期的输出?
怎么样...
<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
。如果不是,根据需要进行调整是一项微不足道的工作。
我正在使用 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">
)。
任何人都可以建议我如何安排我的代码以获得预期的输出?
怎么样...
<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
。如果不是,根据需要进行调整是一项微不足道的工作。