1. 引言
XSLT(Extensible Stylesheet Language Transformations)是一种用于将 XML 文档转换为其他格式(如 HTML、纯文本或其他 XML 结构)的声明式语言。它不仅是数据展示的利器,更是 XML 数据编辑、清洗和重构的核心工具。本文将通过丰富的代码实例,系统讲解如何使用 XSLT 对 XML 文档进行各种编辑操作。
2. XSLT 基础概念
在深入编辑技巧之前,先了解 XSLT 的几个核心概念:
- XSLT 处理器:负责读取 XML 源文档和 XSLT 样式表,并生成输出结果的引擎,常见的有 Saxon、libxml2 等。
- 模板规则:通过
<xsl:template>定义,匹配 XML 树中的特定节点并指定输出内容。 - XPath 表达式:用于在 XML 文档中定位节点,是 XSLT 模板匹配和值提取的基础。
- 样式表:一个符合 XSLT 规范的 XML 文档,以
<xsl:stylesheet>或<xsl:transform>为根元素。
3. 环境准备与第一个示例
本文所有示例均基于 XSLT 1.0 和 2.0 标准,可使用任意主流 XSLT 处理器运行。下面是一个最简单的转换示例,将 XML 转换为 HTML 列表。
源 XML 文件(books.xml):
<?xml version="1.0" encoding="UTF-8"?> <catalog> <book id="b1"> <title>XML 入门</title> <author>张三</author> <price>59.00</price> </book> <book id="b2"> <title>XSLT 实战</title> <author>李四</author> <price>79.00</price> </book> </catalog>对应的 XSLT 样式表(books.xsl):
<?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> <h1>图书列表</h1> <ul> <xsl:for-each select="catalog/book"> <li> <xsl:value-of select="title"/> (作者:<xsl:value-of select="author"/>) </li> </xsl:for-each> </ul> </body> </html> </xsl:template> </xsl:stylesheet>使用命令行工具(如 Saxon)执行转换:
java -jar saxon9he.jar -s:books.xml -xsl:books.xsl -o:books.html输出结果(books.html):
<html> <body> <h1>图书列表</h1> <ul> <li>XML 入门(作者:张三)</li> <li>XSLT 实战(作者:李四)</li> </ul> </body> </html>4. 使用模板匹配编辑 XML
模板匹配是 XSLT 最强大的编辑机制。通过定义多个模板规则,可以精确控制每个节点的处理方式,实现增删改查等编辑操作。
4.1 修改元素内容
下面的示例将所有图书价格上调 10%,并保留两位小数:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 默认复制所有节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 修改价格元素 --> <xsl:template match="price"> <price> <xsl:value-of select="format-number(. * 1.1, '0.00')"/> </price> </xsl:template> </xsl:stylesheet>转换后,<price>59.00</price>变为<price>64.90</price>,<price>79.00</price>变为<price>86.90</price>。
4.2 删除特定节点
以下样式表删除所有价格超过 70 元的图书节点:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 删除价格大于 70 的图书 --> <xsl:template match="book[price > 70]"/> </xsl:stylesheet>注意:空模板规则表示匹配到的节点不产生任何输出,从而实现删除效果。
4.3 新增元素与属性
下面的示例为每本图书添加一个category属性和一个discount子元素:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="book"> <book> <xsl:copy-of select="@*"/> <xsl:attribute name="category">技术</xsl:attribute> <xsl:apply-templates/> <discount>0.85</discount> </book> </xsl:template> </xsl:stylesheet>5. 使用 XPath 精确定位与编辑
XPath 是 XSLT 的查询语言,掌握常用 XPath 表达式可以大幅提升编辑效率。以下是一些常用场景。
5.1 按条件筛选节点
只输出价格在 50 到 80 之间的图书:
<xsl:template match="/"> <result> <xsl:apply-templates select="catalog/book[price >= 50 and price <= 80]"/> </result> </xsl:template>5.2 使用位置索引
选取第一本和最后一本图书:
<xsl:template match="/"> <result> <xsl:copy-of select="catalog/book[1]"/> <xsl:copy-of select="catalog/book[last()]"/> </result> </xsl:template>5.3 使用通配符与轴
选取所有子元素和所有属性:
<xsl:template match="/"> <result> <xsl:copy-of select="catalog/book/*"/> <xsl:copy-of select="catalog/book/@*"/> </result> </xsl:template>6. 高级编辑技巧
6.1 使用变量与参数
通过<xsl:variable>和<xsl:param>实现可复用的编辑逻辑。下面的示例使用参数控制是否包含折扣信息:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="showDiscount" select="'false'"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="book"> <book> <xsl:copy-of select="@*"/> <xsl:apply-templates/> <xsl:if test="$showDiscount = 'true'"> <discount>0.85</discount> </xsl:if> </book> </xsl:template> </xsl:stylesheet>运行时传入参数:
java -jar saxon9he.jar -s:books.xml -xsl:books.xsl -o:books_out.xml showDiscount=true6.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="/"> <result> <xsl:for-each select="catalog/book"> <xsl:sort select="price"><?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="formatPrice"> <xsl:param name="value"/> <xsl:value-of select="format-number($value, '¥#,##0.00')"/> </xsl:template> <xsl:template match="price"> <price> <xsl:call-template name="formatPrice"> <xsl:with-param name="value" select="."/> </xsl:call-template> </price> </xsl:template> </xsl:stylesheet>7. 处理命名空间
处理带命名空间的 XML 时,需要在样式表中声明相同的命名空间。以下示例处理 SOAP 风格的 XML:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ord="http://example.com/orders"> <xsl:template match="/"> <result> <xsl:apply-templates select="//ord:order"/> </result> </xsl:template> <xsl:template match="ord:order"> <order id="{@id}"> <xsl:value-of select="ord:total"/> </order> </xsl:template> </xsl:stylesheet>8. 常见问题与调试技巧
- 输出空白过多:在样式表根元素上添加
<xsl:strip-space elements="*"/>可去除源文档中的空白节点。 - 模板不生效:检查 XPath 表达式是否匹配目标节点,注意命名空间前缀是否正确声明。
- 属性值模板:在属性值中使用
{表达式}语法可以动态生成属性值,如<book id="{@id}">。 - 调试输出:使用
<xsl:message>在处理器控制台输出调试信息。
<xsl:template match="book"> <xsl:message>正在处理图书:<xsl:value-of select="title"/></xsl:message> <!-- 其他处理逻辑 --> </xsl:template>9. 总结
XSLT 提供了一套完整、声明式的 XML 编辑方案。通过模板匹配、XPath 定位、变量参数和命名模板等机制,开发者可以高效地完成 XML 数据的增删改查、格式转换和结构重组。虽然 XSLT 的学习曲线相对陡峭,但一旦掌握其核心思想,处理复杂 XML 编辑任务将变得游刃有余。建议读者结合本文示例,在实际项目中逐步实践,以加深理解。