如何用XSLT将单个XML文件拆分生成多个HTML文件?
用XSLT拆分XML为多个HTML文件的解决方案
首先要说明:你的原始XML缺少根元素(XML文档必须有且仅有一个根节点),所以第一步需要给它补一个根节点,比如<root>,修正后的完整XML如下:
<root> <head>heading ONE</head> <section>Lorem ips</section> <section>Lorem ips</section> <head>heading TWO</head> <head>heading THREE</head> <section>Lorem ips</section> <section>Lorem ips</section> <head>heading FOUR</head> <section>Lorem ips</section> </root>
接下来,我们可以用**XSLT 2.0+**的xsl:result-document特性来生成多个输出文件,结合分组逻辑把每个<head>和它后续的<section>(直到下一个<head>出现)划分为一组,每组对应一个HTML文件。以下是完整的XSLT代码:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 设置默认输出格式为HTML,开启缩进方便阅读 --> <xsl:output method="html" indent="yes" encoding="UTF-8"/> <!-- 匹配根节点作为处理入口 --> <xsl:template match="/root"> <!-- 按<head>元素作为分组起点,将后续的<section>归到当前组 --> <xsl:for-each-group select="*" group-starting-with="head"> <!-- 生成输出文件,用分组序号+heading内容命名,避免文件名重复 --> <xsl:result-document href="output-{position()}-{replace(current-group()[1], '\s', '-')}.html"> <!-- 直接复制当前组的所有元素到输出文件 --> <xsl:copy-of select="current-group()"/> </xsl:result-document> </xsl:for-each-group> </xsl:template> </xsl:stylesheet>
关键逻辑拆解:
- 分组规则:
group-starting-with="head"会把每一个<head>元素作为新组的起始点,后续所有非<head>的元素(也就是你的<section>)都会被归入当前组,直到下一个<head>出现。这完美匹配了你需要的“每个heading对应后续section”的需求。 - 多文件输出:
xsl:result-document是XSLT 2.0+引入的核心特性,专门用来生成多个输出文件。这里的文件名用分组序号+替换空格后的heading内容,既保证唯一性,又能直观看出文件对应哪个heading。 - 内容输出:
current-group()会返回当前分组内的所有元素,用xsl:copy-of直接复制就能得到你期望的输出结构,不需要额外的节点处理。
最终输出效果:
执行这个XSLT后,会生成4个HTML文件,内容完全匹配你的需求:
output-1-heading-ONE.html:包含第一个<head>和两个<section>output-2-heading-TWO.html:仅包含第二个<head>(因为它后面没有<section>就遇到了下一个<head>)output-3-heading-THREE.html:包含第三个<head>和两个<section>output-4-heading-FOUR.html:包含第四个<head>和一个<section>
如果你的XSLT处理器不支持2.0+(比如老版本的Xalan),可能需要用扩展函数或递归逻辑实现,但现在主流处理器(比如Saxon)都支持XSLT 2.0/3.0,上面的方案是最简洁高效的。
内容的提问来源于stack exchange,提问作者Rakesh Sivaraman




