欢迎光临
我们一直在努力

XSLT-if详解:条件判断的语法与实战

1. 引言

XSLT(可扩展样式表语言转换)是处理 XML 文档的强大工具,而 <xsl:if> 是其中最常用的条件判断指令之一。它允许我们在转换过程中根据节点内容、属性值或表达式结果,有选择地输出内容。本文将通过丰富的代码实例,深入讲解 <xsl:if> 的语法、用法、常见陷阱以及与其他条件指令的对比。

2. 基础语法

<xsl:if> 的语法非常简单,核心是 test 属性,它接受一个 XPath 表达式。当表达式的结果为真(true)时,元素内部的内容会被输出;否则被忽略。

<xsl:if test="条件表达式">
<!– 当条件为真时输出的内容 –>
</xsl:if>

下面是一个最基础的示例。假设我们有如下 XML 数据:

<?xml version="1.0" encoding="UTF-8"?>
<books>
<book>
<title>XML 入门</title>
<price>59.00</price>
</book>
<book>
<title>XSLT 高级编程</title>
<price>89.00</price>
</book>
</books>

我们希望只输出价格大于 60 元的书籍:

<?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>
<h2>高价书籍列表</h2>
<xsl:for-each select="books/book">
<xsl:if test="price > 60">
<p>
<xsl:value-of select="title"/>
—— 价格:<xsl:value-of select="price"/> 元
</p>
</xsl:if>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

运行结果:

<html>
<body>
<h2>高价书籍列表</h2>
<p>XSLT 高级编程 —— 价格:89.00 元</p>
</body>
</html>

注意:在 XSLT 1.0 中,> 需要写成 &gt;,< 需要写成 &lt;,以避免与 XML 标签冲突。

3. 常用条件表达式

<xsl:if> 的 test 属性支持丰富的 XPath 表达式。下面分类介绍最常见的几种。

3.1 比较运算

数值和字符串比较是最基础的条件判断。

<!– 数值比较 –>
<xsl:if test="price > 100">高价书</xsl:if>
<xsl:if test="price <= 50">低价书</xsl:if>
<xsl:if test="price = 59.00">价格正好是 59 元</xsl:if>

<!– 字符串比较 –>
<xsl:if test="title = 'XML 入门'">找到入门书</xsl:if>
<xsl:if test="title != 'XSLT 高级编程'">不是高级编程书</xsl:if>

3.2 逻辑运算

使用 and、or、not() 可以组合多个条件。

<!– 与:价格在 50 到 100 之间 –>
<xsl:if test="price >= 50 and price <= 100">
中等价位书籍
</xsl:if>

<!– 或:作者是张三或李四 –>
<xsl:if test="author = '张三' or author = '李四'">
目标作者的作品
</xsl:if>

<!– 非:不是绝版书 –>
<xsl:if test="not(@status = 'out_of_print')">
在售书籍
</xsl:if>

3.3 节点存在性判断

判断某个子元素或属性是否存在,是实际开发中非常常见的需求。

<!– 判断子元素是否存在 –>
<xsl:if test="publisher">
有出版社信息:<xsl:value-of select="publisher"/>
</xsl:if>

<!– 判断属性是否存在 –>
<xsl:if test="@isbn">
ISBN:<xsl:value-of select="@isbn"/>
</xsl:if>

<!– 判断节点集合是否为空 –>
<xsl:if test="not(comments/comment)">
暂无评论
</xsl:if>

3.4 字符串函数

XPath 提供了丰富的字符串处理函数,可以用于更复杂的条件判断。

<!– 判断字符串长度 –>
<xsl:if test="string-length(title) > 10">
标题较长
</xsl:if>

<!– 判断是否以某字符串开头 –>
<xsl:if test="starts-with(title, 'XML')">
标题以 XML 开头
</xsl:if>

<!– 判断是否包含某字符串 –>
<xsl:if test="contains(description, '实战')">
包含"实战"关键词
</xsl:if>

4. 实战案例:图书目录转换

下面通过一个完整的实战案例,综合运用 <xsl:if> 的各种用法。假设我们要将一份图书 XML 转换为带分类标记的 HTML 页面。

<?xml version="1.0" encoding="UTF-8"?>
<library>
<book category="programming">
<title>XSLT 2.0 权威指南</title>
<author>Michael Kay</author>
<price currency="CNY">128.00</price>
<stock>25</stock>
</book>
<book category="database">
<title>SQL 必知必会</title>
<author>Ben Forta</author>
<price currency="CNY">49.00</price>
<stock>0</stock>
</book>
<book category="programming">
<title>深入理解计算机系统</title>
<author>Randal E. Bryant</author>
<price currency="CNY">139.00</price>
<stock>8</stock>
</book>
</library>

对应的 XSLT 样式表:

<?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>
<head>
<title>图书馆藏书</title>
</head>
<body>
<h1>图书馆藏书目录</h1>
<xsl:for-each select="library/book">
<div style="border:1px solid #ccc; margin:10px; padding:10px;">
<h3><xsl:value-of select="title"/></h3>
<p>作者:<xsl:value-of select="author"/></p>
<p>价格:<xsl:value-of select="price"/> 元</p>

<!– 分类标记 –>
<xsl:if test="@category = 'programming'">
<p style="color:blue;">分类:编程技术</p>
</xsl:if>
<xsl:if test="@category = 'database'">
<p style="color:green;">分类:数据库</p>
</xsl:if>

<!– 库存状态提示 –>
<xsl:if test="stock = 0">
<p style="color:red;">暂时缺货</p>
</xsl:if>
<xsl:if test="stock > 0 and stock < 10">
<p style="color:orange;">库存紧张,仅剩 <xsl:value-of select="stock"/> 本</p>
</xsl:if>
<xsl:if test="stock >= 10">
<p style="color:green;">库存充足</p>
</xsl:if>

<!– 价格区间提示 –>
<xsl:if test="price > 100">
<p>这是一本高价技术书籍</p>
</xsl:if>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

输出结果:

<html>
<head>
<title>图书馆藏书</title>
</head>
<body>
<h1>图书馆藏书目录</h1>
<div style="border:1px solid #ccc; margin:10px; padding:10px;">
<h3>XSLT 2.0 权威指南</h3>
<p>作者:Michael Kay</p>
<p>价格:128.00 元</p>
<p style="color:blue;">分类:编程技术</p>
<p style="color:green;">库存充足</p>
<p>这是一本高价技术书籍</p>
</div>
<div style="border:1px solid #ccc; margin:10px; padding:10px;">
<h3>SQL 必知必会</h3>
<p>作者:Ben Forta</p>
<p>价格:49.00 元</p>
<p style="color:green;">分类:数据库</p>
<p style="color:red;">暂时缺货</p>
</div>
<div style="border:1px solid #ccc; margin:10px; padding:10px;">
<h3>深入理解计算机系统</h3>
<p>作者:Randal E. Bryant</p>
<p>价格:139.00 元</p>
<p style="color:blue;">分类:编程技术</p>
<p style="color:orange;">库存紧张,仅剩 8 本</p>
<p>这是一本高价技术书籍</p>
</div>
</body>
</html>

5. 嵌套使用

<xsl:if> 支持嵌套,可以在一个条件内部再判断其他条件,实现更复杂的逻辑。

<xsl:for-each select="library/book">
<xsl:if test="@category = 'programming'">
<xsl:if test="price > 100">
<p>高价编程书:<xsl:value-of select="title"/></p>
</xsl:if>
<xsl:if test="price <= 100">
<p>平价编程书:<xsl:value-of select="title"/></p>
</xsl:if>
</xsl:if>
</xsl:for-each>

虽然嵌套可以实现多分支逻辑,但当分支较多时,代码会变得难以阅读。此时建议使用 <xsl:choose> 配合 <xsl:when> 和 <xsl:otherwise>,结构更清晰。

6. 与 xsl:choose 的对比

<xsl:if> 只有"真"和"假"两个分支,且没有"否则"(else)的概念。当需要多分支或默认分支时,应使用 <xsl:choose>。

<!– 使用 xsl:if 实现多分支(代码冗余) –>
<xsl:if test="score >= 90">优秀</xsl:if>
<xsl:if test="score >= 80 and score < 90">良好</xsl:if>
<xsl:if test="score >= 60 and score < 80">及格</xsl:if>
<xsl:if test="score < 60">不及格</xsl:if>

<!– 使用 xsl:choose 实现同样逻辑(更清晰) –>
<xsl:choose>
<xsl:when test="score >= 90">优秀</xsl:when>
<xsl:when test="score >= 80">良好</xsl:when>
<xsl:when test="score >= 60">及格</xsl:when>
<xsl:otherwise>不及格</xsl:otherwise>
</xsl:choose>

选择建议:

  • 只有单一条件判断时,使用 <xsl:if> 更简洁。
  • 需要"否则"分支或多条件互斥时,使用 <xsl:choose> 更合适。
  • 多个独立条件需要分别判断时,可以连续使用多个 <xsl:if>。

7. 常见陷阱与注意事项

在实际开发中,<xsl:if> 有几个容易踩坑的地方,需要特别注意。

7.1 布尔值转换

XPath 中,空节点集、空字符串、数字 0 和 NaN 都会被转换为 false,其他值转换为 true。这可能导致意想不到的结果。

<!– 陷阱:price 为 0 时,条件为 false –>
<xsl:if test="price">
价格存在且不为 0
</xsl:if>

<!– 正确做法:显式判断节点是否存在 –>
<xsl:if test="price != ''">
价格节点存在
</xsl:if>

7.2 字符串比较的引号问题

在 XML 属性中,字符串值通常使用单引号包裹,避免与属性值的双引号冲突。

<!– 正确:外层双引号,内层单引号 –>
<xsl:if test="title = 'XML 入门'">…</xsl:if>

<!– 错误:内外都是双引号,会导致解析错误 –>
<!– <xsl:if test="title = "XML 入门"">…</xsl:if> –>

7.3 大小写敏感

XPath 的字符串比较是大小写敏感的。如果需要忽略大小写,可以使用 translate() 函数转换。

<!– 大小写敏感 –>
<xsl:if test="category = 'Programming'">…</xsl:if>

<!– 忽略大小写比较 –>
<xsl:if test="translate(category, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = 'programming'">
编程类书籍(不区分大小写)
</xsl:if>

7.4 空白字符处理

XML 中的空白字符可能导致字符串比较失败。使用 normalize-space() 函数可以去除首尾空白并合并连续空白。

<!– 假设 category 的值为 " programming "(带空格) –>
<xsl:if test="normalize-space(category) = 'programming'">
编程类书籍
</xsl:if>

8. XSLT 2.0 中的增强

XSLT 2.0 对条件判断做了一些增强,最显著的是支持 if…then…else 表达式,可以直接在 XPath 中使用。

<!– XSLT 2.0 的 if-then-else 表达式 –>
<xsl:value-of select="if (price > 100) then '高价' else '平价'"/>

<!– 也可以嵌套使用 –>
<xsl:value-of select="if (price > 100) then '高价' else if (price > 50) then '中等' else '低价'"/>

此外,XSLT 2.0 还支持在 <xsl:if> 中使用更丰富的 XPath 2.0 函数,如 matches() 正则匹配、ends-with() 等。

<!– XSLT 2.0 正则匹配 –>
<xsl:if test="matches(title, '^XSLT')">
标题以 XSLT 开头
</xsl:if>

<!– XSLT 2.0 结尾判断 –>
<xsl:if test="ends-with(title, '指南')">
标题以"指南"结尾
</xsl:if>

9. 总结

<xsl:if> 是 XSLT 中最基础也最常用的条件判断指令。通过本文的实例,我们掌握了它的核心语法、常用表达式、嵌套用法以及与 <xsl:choose> 的对比。在实际开发中,建议根据场景选择合适的条件指令:单一条件用 <xsl:if>,多分支互斥用 <xsl:choose>,XSLT 2.0 环境下还可以使用内联的 if-then-else 表达式。同时要注意布尔值转换、引号、大小写和空白字符等常见陷阱,写出健壮可靠的样式表。

赞(0)
未经允许不得转载:171主机测评 » XSLT-if详解:条件判断的语法与实战
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址