如何用XSLT 3.0批量定位并标记大量指定字符串?
XSLT 3.0 批量标记文本中的术语
针对你需要批量标记数百个术语的需求,最高效的方案是用动态生成的正则表达式结合<xsl:analyze-string>,一次性扫描文本完成所有术语匹配,避免循环处理每个术语的低效操作。
完整XSLT代码
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://example.com/functions"> <!-- 自定义函数:转义正则表达式中的特殊字符 --> <xsl:function name="fn:escape-regex" as="xs:string"> <xsl:param name="input" as="xs:string"/> <xsl:sequence select="replace($input, '([\.\\\*\?\+\|\(\)\[\]\{\}\^\$])', '\\$1')"/> </xsl:function> <xsl:template match="/root"> <body> <!-- 加载术语文件 --> <xsl:variable name="terms" select="document('terms.xml')/terms/term"/> <!-- 生成匹配所有术语的正则表达式(带单词边界避免部分匹配) --> <xsl:variable name="term-pattern" select="concat('\b(', string-join($terms!fn:escape-regex(.), '|'), ')\b')"/> <!-- 处理每个段落 --> <xsl:apply-templates select="p"> <xsl:with-param name="pattern" select="$term-pattern"/> </xsl:apply-templates> </body> </xsl:template> <xsl:template match="p"> <xsl:param name="pattern"/> <p> <!-- 分析文本,匹配术语并标记 --> <xsl:analyze-string select="." regex="{$pattern}"> <!-- 匹配到术语时,包裹span标签 --> <xsl:matching-substring> <span class="term"><xsl:value-of select="."/></span> </xsl:matching-substring> <!-- 未匹配的文本直接输出 --> <xsl:non-matching-substring> <xsl:value-of select="."/> </xsl:non-matching-substring> </xsl:analyze-string> </p> </xsl:template> </xsl:stylesheet>
关键说明
术语加载与正则生成:
- 用
document('terms.xml')加载外部术语文件,获取所有<term>节点。 - 通过
string-join将所有术语用|拼接成正则选择器,配合\b单词边界确保只匹配完整单词(避免类似"talk"匹配"talked"的情况)。 - 自定义
fn:escape-regex函数转义术语中的正则特殊字符(如.、*等),防止正则语法错误。
- 用
文本分析与标记:
<xsl:analyze-string>会一次性扫描整个段落文本,匹配所有符合正则的术语。- 匹配到的术语用
<span class="term">包裹,未匹配的文本直接输出,保证原文本结构不变。
注意事项
- 确保术语文件
terms.xml和主XML文件、XSLT文件在同一目录,或在document()函数中使用正确的路径。 - 如果不需要严格匹配完整单词(比如允许术语作为其他词的一部分),可以去掉正则中的
\b边界符。
内容的提问来源于stack exchange,提问作者haggis78
相关产品推荐
相关产品推荐

