XSLT 教程
XSLT 教程
XSL(eXtensible Stylesheet Language,可扩展样式表语言)是用于转换 XML 文档的语言,XSLT 是其转换核心,能把 XML 转为 HTML、文本或其他 XML 格式。
本教程包含
- 基础篇:XSL 语言、XSLT 简介、浏览器支持、转换原理
- 元素篇:template、value-of、for-each、sort、if、choose、apply-templates、import
- 应用篇:样式、客户端/服务端应用、XPath 配合
为什么学习 XSLT
- XML 数据展示与格式转换的标准方案
- 理解数据与展示分离的设计思想
- 旧系统与文档处理中仍有广泛应用
核心思想
XML 数据 + XSLT 样式表 = 输出(HTML/XML/文本)
数据(内容)与样式(表现)完全分离
样式表本身也是 XML 文档XSL 语言
XSL 语言
XSL 家族包含三部分,各自负责不同职责。
XSL 三大组成部分
XSLT (XSL Transformations)
把 XML 转换成其他格式(核心)
XPath (XML Path Language)
在 XML 中导航和查询的路径语言
(XSLT 依赖 XPath 定位节点)
XSL-FO (XSL Formatting Objects)
把 XML 排版为 PDF 等打印格式
(现在使用较少,由 CSS/PDF工具替代)
XSLT 是什么
XSLT = 声明式语言,描述转换规则
基于模板(template)匹配 XML 节点
规则: 匹配什么 → 输出什么
<xsl:template match="/">
<html>
<body>
<xsl:value-of select="/book/title"/>
</body>
</html>
</xsl:template>
XSL 样式表结构
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
...转换规则...
</xsl:template>
</xsl:stylesheet>
XSL vs CSS
CSS: 给 HTML 加样式(展示)
XSLT: 转换 XML 结构(重组内容)
XSL 可以做 CSS 做不到的结构转换XSLT 简介
XSLT 简介
XSLT 把 XML 文档转换为另一个文档,由 W3C 制定标准。
转换过程
输入: XML 文档 + XSLT 样式表
处理: XSLT 处理器遍历 XML 节点,按模板规则输出
输出: HTML / 文本 / 其他 XML
最简单的转换
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>我的图书收藏</h2>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
结合 XML 数据
XML 数据(catalog.xml):
<catalog>
<book><title>Web开发</title></book>
<book><title>数据库基础</title></book>
</catalog>
XSLT 中输出数据:
<xsl:template match="/catalog">
<ul>
<xsl:for-each select="book">
<li><xsl:value-of select="title"/></li>
</xsl:for-each>
</ul>
</xsl:template>
输出:
<ul>
<li>Web开发</li>
<li>数据库基础</li>
</ul>
特点
声明式(描述要什么,而非怎么做)
纯 XML 语法
平台无关(任何语言都有处理器)XSLT 浏览器
XSLT 浏览器
现代浏览器内置 XSLT 处理器,可直接在浏览器中应用 XSLT。
XML 关联样式表
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="catalog.xsl"?>
<catalog>
<book><title>Web开发</title></book>
</catalog>
浏览器打开 XML 文件时自动应用关联的 XSLT,渲染为 HTML。
浏览器兼容
Chrome/Edge/Firefox/Safari 都支持 XSLT 1.0
注意:
XSLT 2.0/3.0 浏览器不支持(需服务端或库)
本地 file:// 打开时部分浏览器限制
测试工具:
xmllint --xinclude / 在线 XSLT 测试器
JavaScript 动态应用
// XSLTProcessor API(浏览器内置)
async function applyXSLT(xmlUrl, xslUrl) {
const xml = await fetch(xmlUrl).then(r => r.text());
const xsl = await fetch(xslUrl).then(r => r.text());
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xml, "application/xml");
const xslDoc = parser.parseFromString(xsl, "application/xml");
const processor = new XSLTProcessor();
processor.importStylesheet(xslDoc);
const result = processor.transformToFragment(xmlDoc, document);
document.getElementById("output").appendChild(result);
}
调试工具
xmllint(Linux/macOS)
XMLSpy / Oxygen(专业编辑器)
浏览器开发者工具(检查输出 HTML)XSLT 转换
XSLT 转换
核心转换机制:模板匹配、内容输出与 XPath 定位。
模板匹配基础
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- 根模板: 匹配文档根 -->
<xsl:template match="/">
<html><body>
<xsl:apply-templates/>
</body></html>
</xsl:template>
<!-- 匹配 book 元素 -->
<xsl:template match="book">
<p><xsl:value-of select="title"/></p>
</xsl:template>
</xsl:stylesheet>
转换流程
1. 处理器从根节点开始
2. 查找匹配的模板(match="/")
3. apply-templates 继续处理子节点
4. 子节点匹配各自模板
5. 生成输出树
(没有匹配模板的节点: 默认只输出文本内容)
命令行转换(xsltproc)
# Linux/macOS 安装 libxslt
sudo apt install libxslt-tools # Ubuntu
brew install libxslt # macOS
# 转换
xsltproc catalog.xsl catalog.xml > output.html
# 或 Python(lxml)
from lxml import etree
xml = etree.parse("catalog.xml")
xsl = etree.parse("catalog.xsl")
transform = etree.XSLT(xsl)
result = transform(xml)
print(str(result))
转换输出类型
<xsl:output method="html"/> <!-- HTML -->
<xsl:output method="xml"/> <!-- XML(默认) -->
<xsl:output method="text"/> <!-- 纯文本 -->
<xsl:output method="html" indent="yes"/> <!-- 缩进 -->XSLT template 元素
XSLT <template> 元素
template 是 XSLT 的核心:定义节点匹配与输出的规则。
基本用法
<xsl:template match="book">
<p>这是一本书</p>
</xsl:template>
match 属性: XPath 表达式,匹配哪些节点
命中后执行模板内容
match 表达式示例
<xsl:template match="/"> 根节点
<xsl:template match="catalog"> catalog 元素
<xsl:template match="book/title"> book 下的 title
<xsl:template match="//book"> 任意层级 book
<xsl:template match="book[@id='1']"> 带属性的 book
<xsl:template match="book[price>50]"> 条件匹配
模板优先级
多个模板匹配同一节点时,按优先级:
1. 更具体的 match 优先
2. 相同优先级用 priority 属性指定
<xsl:template match="book" priority="2">
<xsl:template match="*"> <!-- 通用匹配,优先级低 -->
默认模板行为
没有匹配模板时:
文本节点: 输出文本
元素节点: 递归处理子节点
(相当于透传)
可通过 match="text()" 自定义文本处理
命名模板(函数式)
<xsl:template name="header">
<h1>站点标题</h1>
</xsl:template>
<!-- 调用 -->
<xsl:call-template name="header"/>
<!-- 带参数 -->
<xsl:template name="greet">
<xsl:param name="name"/>
<p>你好, <xsl:value-of select="$name"/>!</p>
</xsl:template>
<xsl:call-template name="greet">
<xsl:with-param name="name" select="'老王'"/>
</xsl:call-template>XSLT value-of 元素
XSLT <value-of> 元素
value-of 提取节点的值并输出到结果。
基本用法
<!-- XML -->
<book>
<title>Web 开发</title>
<price>99</price>
</book>
<!-- XSLT -->
<xsl:template match="book">
<p>书名: <xsl:value-of select="title"/></p>
<p>价格: <xsl:value-of select="price"/> 元</p>
</xsl:template>
输出:
<p>书名: Web 开发</p>
<p>价格: 99 元</p>
select 表达式
<xsl:value-of select="title"/> 子元素值
<xsl:value-of select="."/> 当前节点文本
<xsl:value-of select="@id"/> 属性值
<xsl:value-of select="/catalog/book/title"/> 绝对路径
<xsl:value-of select="count(book)"/> 函数结果
<xsl:value-of select="string(price)"/> 转字符串
属性输出
<!-- XML: <book id="5">...</book> -->
<xsl:template match="book">
<div id="book-<xsl:value-of select='@id'/>">
<xsl:value-of select="title"/>
</div>
</xsl:template>
// 注意: 属性中嵌入 value-of 写法较特殊
// 更清晰方式:
<xsl:attribute name="id">
<xsl:value-of select="concat('book-', @id)"/>
</xsl:attribute>
输出字符串常量
<xsl:value-of select="'常量字符串'"/> <!-- 单引号包字符串 -->
<xsl:value-of select="'100'"/> <!-- 数字字符串 -->
注意
value-of 只输出第一个匹配节点的值
多个值可用 for-each 或 select 用 xpath 序列(XSLT2)
节点不存在时输出空(不报错)XSLT for-each 元素
XSLT <for-each> 元素
for-each 遍历节点集合,对每个节点重复执行内容。
基本用法
<!-- XML -->
<catalog>
<book><title>HTML</title></book>
<book><title>CSS</title></book>
<book><title>JS</title></book>
</catalog>
<!-- XSLT: 输出所有书名 -->
<xsl:template match="/">
<ul>
<xsl:for-each select="catalog/book">
<li><xsl:value-of select="title"/></li>
</xsl:for-each>
</ul>
</xsl:template>
当前节点上下文
<xsl:for-each select="book">
<!-- 循环内当前节点是 book -->
<xsl:value-of select="title"/> <!-- book/title -->
<xsl:value-of select="@id"/> <!-- book 的属性 -->
<xsl:value-of select="."/> <!-- book 全部文本 -->
</xsl:for-each>
嵌套 for-each
<xsl:for-each select="catalog">
<xsl:for-each select="book">
<p><xsl:value-of select="title"/></p>
</xsl:for-each>
</xsl:for-each>
筛选与限定
<!-- 只遍历价格大于50的书 -->
<xsl:for-each select="book[price > 50]">
<!-- 前3本 -->
<xsl:for-each select="book[position() <= 3]">
<!-- 遍历属性值匹配的 -->
<xsl:for-each select="book[@category='web']">
for-each vs apply-templates
for-each: 循环体内直接处理(简单场景)
apply-templates: 委托给模板(模块化,推荐复杂场景)
简单重复输出用 for-each 更直观XSLT sort 元素
XSLT <sort> 元素
sort 对 for-each 或 apply-templates 的结果排序。
基本排序
<xsl:for-each select="book">
<xsl:sort select="title"/> <!-- 按书名排序(默认升序) -->
<p><xsl:value-of select="title"/></p>
</xsl:for-each>
降序排序
<xsl:sort select="price" order="descending"/> <!-- 价格降序 -->
数值排序
<xsl:sort select="price" data-type="number"/>
<!-- data-type: text(默认)/number/date -->
<!-- 不指定时按字符串排序(100 < 20 问题!) -->
多级排序
<xsl:sort select="category"/> <!-- 先按分类 -->
<xsl:sort select="price" order="descending" data-type="number"/>
<!-- 再按价格降序 -->
自定义排序键
<xsl:sort select="substring(title, 1, 1)"/> <!-- 按首字母 -->
完整示例
<xsl:template match="/">
<table>
<xsl:for-each select="catalog/book">
<xsl:sort select="price" data-type="number"
order="descending"/>
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="price"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
注意
sort 必须是 for-each/apply-templates 的第一个子元素
排序只在循环内部生效XSLT if 元素
XSLT <if> 元素
if 根据条件决定是否输出内容。
基本用法
<xsl:if test="price > 50">
<p>这是一本高价书</p>
</xsl:if>
test: 条件表达式(布尔),为真时执行
完整示例
<xsl:for-each select="book">
<p>
<xsl:value-of select="title"/>
<xsl:if test="price > 100">
<b>(高价)</b>
</xsl:if>
</p>
</xsl:for-each>
条件表达式
price > 50 数值比较
@category = 'web' 属性等于
title = 'HTML' 元素文本等于
price > 50 and price < 100 与
@web = 'true' or ... 或
not(@hidden) 取反
position() = 1 第一个
count(book) > 3 函数结果
特殊字符转义:
> > < <
& & " "
判断节点存在
<xsl:if test="author"> <!-- 存在 author 子元素 -->
<xsl:if test="not(author)"> <!-- 不存在 -->
<xsl:if test="@id"> <!-- 有 id 属性 -->
if 的局限
if 没有 else!
多分支用 choose(见下一章)
if 只控制自身内容输出XSLT choose 元素
XSLT <choose> 元素
choose-when-otherwise 实现 if-else 多分支逻辑。
基本结构
<xsl:choose>
<xsl:when test="price > 100">
<p>高价书</p>
</xsl:when>
<xsl:when test="price > 50">
<p>中价书</p>
</xsl:when>
<xsl:otherwise>
<p>低价书</p>
</xsl:otherwise>
</xsl:choose>
规则:
when 从上到下匹配第一个为真的
otherwise 相当于 else(可选)
都不满足且无 otherwise 则无输出
示例: 根据属性输出
<xsl:template match="book">
<xsl:choose>
<xsl:when test="@category='web'">
<span class="web">前端</span>
</xsl:when>
<xsl:when test="@category='db'">
<span class="db">数据库</span>
</xsl:when>
<xsl:otherwise>
<span>其他</span>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
复杂条件
<xsl:when test="price > 50 and inStock='true'">
choose 嵌套
<xsl:choose>
<xsl:when test="a">
<xsl:choose>...</xsl:choose> <!-- 嵌套 -->
</xsl:when>
</xsl:choose>
if vs choose
if: 单个条件,无 else
choose: 多分支 if-else 完整结构
两个条件以上或需要 else 时用 chooseXSLT apply-templates 元素
XSLT <apply-templates> 元素
apply-templates 是模板驱动的核心:把处理权交给匹配的模板。
基本机制
<xsl:template match="/">
<html><body>
<xsl:apply-templates/> <!-- 处理所有子节点 -->
</body></html>
</xsl:template>
<xsl:template match="book">
<p><xsl:value-of select="title"/></p>
</xsl:template>
流程:
根模板 apply-templates
→ 子节点(book)自动匹配到对应模板
→ 各模板输出自己的内容
指定处理节点
<xsl:apply-templates select="book"/> 只处理 book
<xsl:apply-templates select="book/title"/> 处理特定元素
<xsl:apply-templates select="@*"/> 处理属性
<xsl:apply-templates select="text()"/> 处理文本
带参数调用
<xsl:apply-templates select="book">
<xsl:with-param name="highlight" select="'true'"/>
</xsl:apply-templates>
<xsl:template match="book">
<xsl:param name="highlight"/>
<p class="{@id}">...</p>
</xsl:template>
模板模式(mode)
同一节点可被不同模板处理(按 mode 区分):
<xsl:template match="book"> <!-- 默认 -->
<xsl:template match="book" mode="short"> <!-- 简短版 -->
<xsl:apply-templates select="book" mode="short"/>
for-each vs apply-templates
for-each: 手动循环,代码集中
apply-templates: 自动分发,模板可复用、易扩展
复杂/可扩展项目推荐 apply-templatesXSLT import 元素
XSLT <import> 元素
import 引入其他样式表,实现样式表复用与覆盖。
导入样式表
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="common.xsl"/> <!-- 必须位于最前 -->
<!-- 本文件模板优先于导入的 -->
<xsl:template match="book">
<p>自定义版: <xsl:value-of select="title"/></p>
</xsl:template>
</xsl:stylesheet>
优先级规则
导入的模板优先级低
本文件的模板覆盖导入的同名模板
多个导入: 后导入的优先(import 顺序)
覆盖后可调用原模板:
<xsl:apply-imports/> <!-- 调用被覆盖的导入模板 -->
include vs import
include: 内容合并,模板平等(冲突报错)
import: 引入且可被覆盖(推荐,类似继承)
<xsl:include href="header.xsl"/>
应用场景
公共模板库(页头/页脚/导航)
主题定制(基础样式表 + 覆盖)
多站点共享转换逻辑
版本化样式表XSLT 样式
XSLT 样式
XSLT 输出 HTML 时配合 CSS 控制展示效果。
输出中加 CSS
<xsl:template match="/">
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>...</body>
</html>
</xsl:template>
条件加类名
<xsl:template match="book">
<p>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="price > 100">expensive</xsl:when>
<xsl:otherwise>normal</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:value-of select="title"/>
</p>
</xsl:template>
输出: <p class="expensive">...</p>
行内样式简写
<p style="color: {color}">
<!-- {表达式} 在大括号中求值 -->
<p class="{@category}"> <!-- 属性值做类名 -->
生成表格样式
<table border="1">
<xsl:for-each select="book">
<xsl:sort select="title"/>
<tr>
<td><xsl:value-of select="title"/></td>
<td align="right"><xsl:value-of select="price"/></td>
</tr>
</xsl:for-each>
</table>
注意
XSLT 负责结构,CSS 负责视觉
输出 HTML 时注意转义:
文本内容用 <xsl:value-of> 自动转义
需要输出原始 HTML 用 disable-output-escapingXSLT 客户端应用
XSLT 客户端应用
在浏览器端应用 XSLT,把 XML 渲染为 HTML 页面。
1. XML 关联 XSL 文件
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="catalog.xsl"?>
<catalog>...</catalog>
直接浏览器打开 XML 文件即可看到转换结果。
2. JavaScript 动态转换
async function transformXml(xmlUrl, xslUrl, targetId) {
const [xmlText, xslText] = await Promise.all([
fetch(xmlUrl).then(r => r.text()),
fetch(xslUrl).then(r => r.text()),
]);
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
const xslDoc = parser.parseFromString(xslText, "text/xml");
if (parser.parseFromString("", "text/xml").getElementsByTagName("parsererror").length) {
console.error("XML 解析错误");
return;
}
const xsltProc = new XSLTProcessor();
xsltProc.importStylesheet(xslDoc);
const resultDoc = xsltProc.transformToDocument(xmlDoc);
document.getElementById(targetId).innerHTML =
new XMLSerializer().serializeToString(resultDoc.documentElement);
}
// 使用
transformXml("data.xml", "style.xsl", "content");
3. 优缺点
优点: 数据与展示分离,样式表可复用
无需服务端处理,减轻服务器负担
缺点: 浏览器只支持 XSLT 1.0
复杂转换逻辑难以调试
现代前端多用 JS 模板引擎替代
4. 何时使用
静态 XML 数据展示
XML 文档预览
老系统兼容
学习 XSLT 场景XSLT 服务端应用
XSLT 服务端应用
在服务端完成 XSLT 转换,输出最终 HTML 给浏览器。
Python + lxml
from lxml import etree
def transform(xml_file, xsl_file):
xml = etree.parse(xml_file)
xsl = etree.parse(xsl_file)
transform = etree.XSLT(xsl)
result = transform(xml)
return str(result)
# Flask 示例
from flask import Flask, Response
app = Flask(__name__)
@app.route("/catalog")
def catalog():
html = transform("catalog.xml", "catalog.xsl")
return Response(html, mimetype="text/html")
Java + JAXP
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class XsltDemo {
public static void main(String[] args) throws Exception {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(
new StreamSource("catalog.xsl"));
transformer.transform(
new StreamSource("catalog.xml"),
new StreamResult("catalog.html"));
}
}
Node.js + xslt-processor
npm install xslt-processor
const { xsltProcess, xmlParse } = require("xslt-processor");
const xml = xmlParse(fs.readFileSync("catalog.xml", "utf-8"));
const xsl = xmlParse(fs.readFileSync("catalog.xsl", "utf-8"));
const html = xsltProcess(xml, xsl);
console.log(html);
服务端 XSLT 优势
支持 XSLT 1.0-3.0 全部特性
数据缓存与性能可控
统一转换逻辑(客户端不感知)
适合: 内容管理、报表生成、数据交换
PHP 示例
<?php
$xml = new DOMDocument();
$xml->load("catalog.xml");
$xsl = new DOMDocument();
$xsl->load("catalog.xsl");
$proc = new XSLTProcessor();
$proc->importStylesheet($xsl);
echo $proc->transformToXML($xml);
?>XSLT 与 XPath
XSLT 与 XPath
XPath 是 XSLT 的定位语言,掌握常用 XPath 是写 XSLT 的前提。
XPath 基础
/catalog 根下的 catalog
/catalog/book catalog 下的 book
book/title book 下的 title
//book 文档中任意 book
//@id 任意 id 属性
./title 当前节点下的 title
../price 父节点的 price
谓词(筛选)
book[1] 第一个 book
book[last()] 最后一个
book[position() < 3] 前两个
book[@id='5'] id 属性为 5
book[price > 50] 价格大于50
book[title='HTML'] title 为 HTML
book[@category and price] 同时有属性与子元素
XPath 函数
text() 取文本节点
count(book) 数量
string(.) 转字符串
concat(a,b) 连接
contains(title,'Web') 包含
starts-with(@id,'b') 开头
normalize-space(title) 去空白
substring(title,1,3) 子串
translate(text,'abc','ABC') 替换字符
轴(Axes)
child:: 子节点(默认)
parent:: 父节点
ancestor:: 祖先节点
descendant:: 后代节点
following-sibling:: 后续兄弟
preceding-sibling:: 前兄弟
// 常用简写:
. 当前节点 .. 父节点 @ 属性
在 XSLT 中的使用
<xsl:value-of select="//book[2]/title"/>
<xsl:if test="contains(title, '教程')">
<xsl:for-each select="book[price > 30]">
调试 XPath
浏览器 DevTools: $x("//book")
Python: lxml xpath()
命令行: xmllint --xpath '//book' catalog.xmlXSLT 变量与参数
XSLT 变量与参数
variable 与 param 定义可复用的值。
变量(xsl:variable)
<!-- 定义 -->
<xsl:variable name="title" select="'Web 开发'"/>
<xsl:variable name="maxPrice" select="100"/>
<xsl:variable name="bookCount" select="count(/catalog/book)"/>
<!-- 使用($ 引用) -->
<p><xsl:value-of select="$title"/></p>
<xsl:if test="price < $maxPrice">
<!-- 变量值也可由内容构造 -->
<xsl:variable name="greeting">
<b>欢迎访问!</b>
</xsl:variable>
变量作用域
变量只在定义它的模板内可见
<xsl:variable> 在同一层级内有效
(类似局部变量)
全局变量: 定义在 stylesheet 顶层,处处可用
<xsl:variable name="appName" select="'我的应用'"/>
参数(xsl:param)
<!-- 模板参数 -->
<xsl:template name="item">
<xsl:param name="label"/> <!-- 可默认值 -->
<xsl:param name="value" select="'N/A'"/>
<p><xsl:value-of select="$label"/>: <xsl:value-of select="$value"/></p>
</xsl:template>
<xsl:call-template name="item">
<xsl:with-param name="label" select="'价格'"/>
<xsl:with-param name="value" select="price"/>
</xsl:call-template>
顶层参数(外部传入)
<xsl:param name="mode"/> <!-- 顶层定义 -->
// xsltproc 传入
xsltproc --stringparam mode dark catalog.xsl catalog.xml
// Python
transform = etree.XSLT(xsl)
result = transform(xml, mode=etree.XSLT.strparam("dark"))
变量 vs 参数
variable: 内部定义的值
param: 外部/调用方传入的值(可设默认)
两者都是不可变(类似常量)XSLT 高级特性
XSLT 高级特性
XSLT 1.0 之外的扩展能力与技巧。
常用函数
<xsl:value-of select="format-number(price, '#,##0.00')"/>
<!-- 数字格式化: 1,234.56 -->
<xsl:value-of select="sum(//book/price)"/>
<!-- 求和 -->
<xsl:value-of select="string-length(title)"/>
<!-- 长度 -->
<xsl:value-of select="normalize-space(text())"/>
<!-- 清理空白 -->
输出转义控制
<!-- 输出原始 HTML(慎用) -->
<xsl:value-of select="content" disable-output-escaping="yes"/>
<!-- 普通 value-of 会转义 < > & -->
消息与调试
<xsl:message terminate="yes">错误: 缺少必要数据</xsl:message>
<!-- terminate=yes 终止转换 -->
<!-- 默认打印警告继续执行 -->
文本输出
<xsl:text>静态文本</xsl:text> <!-- 保留空白 -->
<xsl:text disable-output-escaping="yes"><br/></xsl:text>
XSLT 2.0+ 增强(服务端)
分组: <xsl:for-each-group>
多输出: <xsl:result-document>
正则: analyze-string
多个输入/输出文档
日期与正则类型
更好的类型系统(XSD)
(XSLT 2.0/3.0 需 Saxon 等处理器)
Saxon(高级处理器)
# Java
java -jar saxon-he.jar -s:catalog.xml -xsl:catalog.xsl -o:out.html
# Python(SaxonC)
# pip install saxoncheXSLT 总结与资源
XSLT 总结与资源
恭喜完成 XSLT 教程!回顾知识体系与学习资源。
知识体系回顾
- XSL 家族:XSLT(转换)+ XPath(定位)+ XSL-FO(排版)
- 模板机制:template 匹配节点,apply-templates 分发
- 取值输出:value-of、for-each、文本与属性
- 流程控制:if、choose-when-otherwise、sort
- 复用:命名模板、import/include、变量与参数
- 定位:XPath 路径、谓词、函数、轴
- 应用:客户端(XSLTProcessor)、服务端(xsltproc/lxml/Saxon)
核心思想
1. 数据与展示分离
2. 声明式编程(描述规则,处理器执行)
3. 模板驱动(节点 → 输出)
4. XPath 是选择数据的语言
学习资源
W3C 规范: w3.org/TR/xslt
W3Schools XSLT 教程(中文版)
XPath 教程: w3schools.com/xml/xpath_intro.asp
在线练习: 免费在线 XSLT 测试器
工具推荐
xsltproc 命令行(快速测试)
Saxon 高级处理器(XSLT 2.0/3.0)
Oxygen XML 专业编辑器
XMLSpy 可视化调试
浏览器 DevTools 检查输出
现代视角
现代前端多用 JS 模板/框架渲染数据
但 XSLT 仍是 XML 标准转换工具:
文档发布流水线
数据交换格式转换
旧系统维护
学习声明式转换思想
掌握 XSLT 模板与 XPath,你就理解了 XML 生态中最强大的转换机制,这也会加深你对数据-表现分离架构的理解。