XSLT(Extensible Stylesheet Language Transformations)是一种声明式的 XML 转换语言:写一份"样式表"描述输出规则,处理器自动把源文档整树变形。模板匹配 + 递归应用是它的核心机制。承上:解析好的树在这里变成另一种形态;启下:样式表内部大量使用 XPath,5.3 节继续深挖这门寻址语言。
命令式思维是"取出每本书、拼接字符串、追加到结果"。XSLT 反过来:描述输出结构,遇到哪种节点套哪个模板。写样式表像给文档配"翻译规则册",翻译由处理器执行。
规则册(样式表)本体是 XML,xsl: 前缀的元素是转换指令(4.2 节伏笔回收),其余元素原样输出:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <!-- 匹配根:翻译从这开始 --> <html><body> <table border="1"> <tr><th>书号</th><th>书名</th><th>库存</th></tr> <xsl:for-each select="inventory/book"> <!-- XPath 选出所有 book --> <tr> <td><xsl:value-of select="@sku"/></td> <!-- 取属性 --> <td><xsl:value-of select="title"/></td> <!-- 取子元素文本 --> <td><xsl:value-of select="stock"/></td> </tr> </xsl:for-each> </table> </body></html> </xsl:template> </xsl:stylesheet>
对第 1 章那份 inventory 文档执行转换:
命令:xsltproc inventory.xsl inventory.xml 输出(节选): <html><body><table border="1"> <tr><th>书号</th><th>书名</th><th>库存</th></tr> <tr><td>9787111407010</td><td>算法导论</td><td>42</td></tr> <tr><td>9787115428028</td><td>JavaScript DOM编程艺术</td><td>7</td></tr> </table></body></html>
一份样式表,把数据文档变成了网页表格——同一份数据再配另一份样式表,就能变成 CSV、另一种 XML、纯文本报表。
for-each 是入门拐杖,XSLT 的正牌机制是模板。等价的模板写法:
<xsl:template match="/"> <html><body> <table border="1"> <tr><th>书号</th><th>书名</th><th>库存</th></tr> <xsl:apply-templates select="inventory/book"/> <!-- 把所有 book 节点派发给匹配它们的模板 --> </table> </body></html> </xsl:template> <xsl:template match="book"> <tr> <td><xsl:value-of select="@sku"/></td> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="stock"/></td> </tr> </xsl:template> <!-- 处理器递归下钻:apply-templates 找到最匹配的模板 → 模板内可再 apply -->
模板机制的价值在大文档显现:各节点类型各配各的模板,新增节点类型加一个模板即可,互不牵连。配合 xsl:sort 排序、xsl:if / xsl:choose 条件,规则册表达力覆盖绝大多数转换需求;XSLT 2.0 还加入分组、正则、多输出。
一个常见新手事故:写了 <xsl:template match="title"> 却没写 match="/",处理器对源文档套用内置模板(默认把文本节点原样拷出),输出一串书名数字、结构全无——内置模板的存在让"漏写模板"不报错而输出怪异,排错时先想到它。
💡 两种心智像:样式表是模具(源数据灌进模具出形状);也是翻译规则册(处理器逐节点查册翻译)。模具强调"输出结构固定",规则册强调"递归匹配",两个都对,交替用。
背景:出版社的书目主档是 XML,需同时产出网页书目与供经销商系统的另一种 XML。操作:同一主档配两份样式表——to-html.xsl(上文的表格模板改版)与 to-partner.xsl(把 book 元素重命名为 product、price 单位挪进属性)。结果:主档一处修改,两个出口自动一致;任何新渠道=新样式表,主档零改动。解读:这是 XSLT 的经典位形——单一数据源、多份转换出口,替代"为每个渠道维护一份导出代码"的命令式方案。变式:渠道要求 JSON 时,XSLT 3.0 可直接输出 JSON;停在 1.0 的工具链则输出"JSON 形状的文本"再后处理。
转换时"选哪些节点"全靠 XPath——下一节把这门寻址语言从表达式到 FLWOR 讲透。