XSLT中字符串替换首选replace()(XSLT 2.0+,支持正则、子串、全局/忽略大小写),单字符映射用translate()(XSLT 1.0/2.0均支持,仅一对一字符替换);XSLT 1.0需递归模板模拟子串替换。

XSLT 中实现字符串替换主要有两个函数:translate() 和 replace(),它们用途不同、能力差异大,选错容易出错。
translate():单字符一对一替换,简单但限制多
translate() 只能做“字符到字符”的映射,不能处理子字符串,也不能增删字符长度。它接收三个参数:原字符串、要被替换的字符集、替换成的字符集。
- 三个参数长度必须一致,否则多余字符会被忽略(比如第二个参数比第三个长,多出的字符会被删掉)
- 它不支持正则,也不支持模糊匹配,只逐个扫描原字符串中的每个字符,查表替换
- 常用于大小写转换、清理非法字符、简单符号映射
例子:把所有 a 换成 A,b 换成 B:
结果是 ABc123;注意 c 不在替换列表里,保持不变。
replace():基于正则的灵活替换,XSLT 2.0+ 才有
replace() 是真正的字符串替换主力,支持正则表达式,可替换子串、支持捕获组、能控制全局/首次匹配,功能接近编程语言里的 String.replace()。
- 需要 XSLT 2.0 或更高版本(Saxon、Altova、libxslt 1.1.27+ 等处理器支持)
- 语法:
replace($input, $pattern, $replacement, $flags?) -
$flags常用 g(全局)、i(忽略大小写)、gi(两者都用)
例子:把所有数字替换成星号,或把 "cat" 替换为 "dog"(不区分大小写):
结果:I have *** cats and *** dogs
结果:dog and dog
XSLT 1.0 没有 replace()?可以模拟但很麻烦
如果只能用 XSLT 1.0(比如老版 IE 或某些遗留系统),replace() 不可用,translate() 又太弱,就得靠递归模板手动实现子串替换。
- 原理:用
substring-before()和substring-after()配合递归,每次找第一个匹配位置,拼接前后 + 替换内容 - 不支持正则,只能替换固定字符串(如把 "old" 换成 "new")
- 性能差、代码长、易出边界错误,仅建议实在无法升级时使用
简单示意逻辑(非完整代码):
定义模板 match-string-replace,输入 text、from、to;若 contains(text, from),就拼接 substring-before + to + 递归调用 substring-after,否则返回原文。怎么选?看需求再决定
- 只换单个字符(比如全转大写、删掉标点)→ 用
translate(),轻量又高效 - 要换词、换模式、带条件(如“所有邮箱”、“连续空格变一个”)→ 必须用
replace(),且确认处理器支持 XSLT 2.0+ - 卡在 XSLT 1.0 又必须换子串 → 接受递归模板的复杂性,或考虑在外部预处理字符串
基本上就这些。别硬用 translate() 去干 replace() 的活,也别在 1.0 环境下幻想正则——先看清版本和需求,再动手。










