XSLT怎么实现字符串替换 translate()和replace()

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

XSLT 中实现字符串替换主要有两个函数:translate()replace(),它们用途不同、能力差异大,选错容易出错。

translate():单字符一对一替换,简单但限制多

translate() 只能做“字符到字符”的映射,不能处理子字符串,也不能增删字符长度。它接收三个参数:原字符串、要被替换的字符集、替换成的字符集。

  • 三个参数长度必须一致,否则多余字符会被忽略(比如第二个参数比第三个长,多出的字符会被删掉)
  • 它不支持正则,也不支持模糊匹配,只逐个扫描原字符串中的每个字符,查表替换
  • 常用于大小写转换、清理非法字符、简单符号映射

例子:把所有 a 换成 Ab 换成 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 环境下幻想正则——先看清版本和需求,再动手。