我的 XHTML 输入:
<h1 class="section">Text</h1>
<h2 class="section">More text</h2>
所需的 XHTML 输出:
<div class="section">
<h1 class="section">Text</h1>
<h2 class="section">More text</h2>
</div>
因此,该group-adjacent
方法似乎是合适的。下面的代码将对h1
andh2
节点做正确的事情,但它会删除<body>
节点中的所有其他内容,包括<body>
标签本身。
显然我犯了一个错误,但我还不足以for-each-group
理解它在哪里。
谢谢。
<xsl:template match="xhtml:body">
<xsl:for-each-group select="xhtml:h1|xhtml:h2" group-adjacent="@class">
<xsl:choose>
<xsl:when test="current-grouping-key()='section'">
<xsl:element name="div">
<xsl:attribute name="class">
<xsl:value-of select="current-grouping-key()"/>
</xsl:attribute>
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
更新:我不明白的是,它for-each-group
本质上充当了您指向的任何节点的过滤器。因此,如果要保留每个子节点,则原始命令必须包含select="*"
. 此外,分组规则必须确保每个子节点最终都在一个组中。这意味着group-adjacent
不是工作的正确工具;group-starting-with
是。
下面的模板将整个<body>
XHTML 文件分成以 . 开头的组h1
。(注意:这个分组规则依赖于 anh1
总是<body>
XHTML 中的第一个子节点的假设。)然后我遍历组,使用条件查看每个组中的前两个节点以查看它们是否匹配我的标准。如果是这样,我将它们包装在我的<div>
.
我仍然对是否有更惯用的 XSLT 解决方案感兴趣,因为我所做的基本上是在 XSLT 中编写 Python。
<xsl:template match="xhtml:body">
<xsl:copy>
<!--Divide file into groups of nodes starting with h1 tags-->
<xsl:for-each-group select="*" group-starting-with="xhtml:h1">
<xsl:choose>
<!-- if the group starts with h1.section + h2.section -->
<xsl:when test="current-group()[1][@class='section'] and current-group()[2][name() = 'h2'] and current-group()[2][@class = 'section']">
<!--wrap in a div tag-->
<div class="section">
<xsl:apply-templates select="current-group()[1]"/>
<xsl:apply-templates select="current-group()[2]"/>
</div>
<!--then process the rest of the nodes in this group normally-->
<xsl:apply-templates select="current-group()[position()>=3]"/>
</xsl:when>
<xsl:otherwise>
<!--process normally-->
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>