XSLT 控制结构
本章定位 :掌握 XSLT 的条件判断和循环结构——
xsl:if(单路条件)、xsl:choose/when/otherwise(多路分支)、xsl:for-each(循环遍历)和xsl:sort(排序)。
定义与作用
XSLT 是一种声明式语言,但实际转换中经常需要条件逻辑和循环。XSLT 提供了四种控制结构:
xsl:if:单路条件(只有 if,没有 else)xsl:choose/when/otherwise:多路分支(if-elseif-else)xsl:for-each:遍历节点集xsl:sort:排序
注意:XSLT 的 if 没有 else 分支——这是它与传统编程语言最大的语法差异,需要多路分支时必须用 choose/when/otherwise。
核心原理:控制流对比
三种控制流程各有用途——if 最简单但无 else,choose 是多路选择,for-each 可配合 sort 实现排序遍历。
语法/结构要点
xsl:if(单路条件)
<xsl:if test="price > 30">
<strong>贵!</strong>
</xsl:if>
xsl:choose(多路分支)
<xsl:choose>
<xsl:when test="price > 50">高档</xsl:when>
<xsl:when test="price > 30">中档</xsl:when>
<xsl:otherwise>经济</xsl:otherwise>
</xsl:choose>
xsl:for-each + xsl:sort
<xsl:for-each select="bookstore/book">
<xsl:sort select="price" data-type="number" order="ascending"/>
<p><xsl:value-of select="title"/> — <xsl:value-of select="price"/></p>
</xsl:for-each>
完整示例:黄俪用控制结构生成报表
场景说明
飞翔科技的测试 黄俪 要为测试结果 XML 生成一份 HTML 报告。需求:按等级分组(高优先级先显示)、通过的标绿、失败的标红,最后统计通过率。
XML 数据
<test-results>
<case id="TC001" priority="high" status="pass">登录功能</case>
<case id="TC002" priority="low" status="fail">界面字体</case>
<case id="TC003" priority="high" status="fail">支付回调</case>
<case id="TC004" priority="medium" status="pass">搜索过滤</case>
<case id="TC005" priority="low" status="pass">分页导航</case>
</test-results>
XSLT 处理
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html><body>
<h2>测试报告</h2>
<!-- 统计 -->
<p>总用例: <xsl:value-of select="count(//case)"/></p>
<p>通过: <xsl:value-of select="count(//case[@status='pass'])"/></p>
<p>失败: <xsl:value-of select="count(//case[@status='fail'])"/></p>
<!-- 按优先级排序 -->
<table border="1">
<tr><th>用例</th><th>优先级</th><th>结果</th></tr>
<xsl:for-each select="test-results/case">
<xsl:sort select="
string-length(
substring-before('highmediumlow', @priority)
)" data-type="number" order="ascending"/>
<xsl:choose>
<xsl:when test="@status='pass'">
<tr style="background-color:#d4edda;">
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="@priority"/></td>
<td>通过</td>
</tr>
</xsl:when>
<xsl:otherwise>
<tr style="background-color:#f8d7da;">
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="@priority"/></td>
<td>失败</td>
</tr>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet>
操作结果
生成的 HTML 报告中:
- 高优先级用例排在前面(TC001、TC003)
- 通过用例绿色背景,失败用例红色背景
- 顶部显示统计:总5个,通过3个,失败2个
易错场景
错误一:以为 xsl:if 有 else
<!-- ❌ XSLT 没有 else -->
<xsl:if test="@status='pass'">通过</xsl:if>
<xsl:else>失败</xsl:else> <!-- 语法错误! -->
<!-- ✅ 用 choose/when/otherwise -->
<xsl:choose>
<xsl:when test="@status='pass'">通过</xsl:when>
<xsl:otherwise>失败</xsl:otherwise>
</xsl:choose>
错误二:xsl:sort 位置错误
xsl:sort 必须是 xsl:for-each 或 xsl:apply-templates 的 第一个子元素 。
<!-- ✅ -->
<xsl:for-each select="book">
<xsl:sort select="price"/>
<p>...</p>
</xsl:for-each>
<!-- ❌ sort 不在第一个 -->
<xsl:for-each select="book">
<p>...</p>
<xsl:sort select="price"/>
</xsl:for-each>
面试考点
| 考点 | 参考答案要点 |
|---|---|
| XSLT 的 if 为什么没有 else? | XSLT 是声明式语言,设计上倾向于用模板匹配(多模板 + 不同 match)实现分支。需要 else 时用 xsl:choose/when/otherwise |
| for-each 和 apply-templates 的选择原则? | for-each 适合简单的遍历输出(如表格行);apply-templates 支持多模板分派和递归,适合复杂、层次化的转换 |
| xsl:sort 的排序类型支持哪些? | data-type 支持 text(字典序)和 number(数值序),order 支持 ascending 和 descending。多个 sort 可级联 |