XSLT中replace()正则\s+无法匹配多空格问题求助
XSLT中replace()的\s+无法匹配多空格的原因分析
示例XML
<para>Doors 1 (<extref targetid="REF1034248349404" id="abc-123"/>) and 2 (<extref targetid="REF1034248370394" id="xyz-123"/>) closed, for temporary installation see <xref xrefid="def-123"/> </para>
XSLT模板
<xsl:template match="para"> <p>Text as is</p> <xsl:for-each select="text()/normalize-space()"> <text><xsl:value-of select="."/></text> </xsl:for-each> <p>Text with '\s+' replaced with '*'</p> <xsl:for-each select="text()/normalize-space()"> <text><xsl:value-of select="replace(., '\s+', '*')"/></text> </xsl:for-each> </xsl:template>
预期输出
<p>Text as is</p> <text>Doors 1 (</text> <text>) and 2 (</text> <text>) closed, for temporary installation see</text> <text/> <p>Text with '\s+' replaced with '*'</p> <text>Doors*1*(</text> <text>)*and*2*(</text> <text>)*closed,*for*temporary*installation*see</text> <text/>
实际输出
<p>Text as is</p> <text>Doors 1 (</text> <text>) and 2 (</text> <text>) closed, for temporary installation see</text> <text/> <p>Text with '\s+' replaced with '*'</p> <text>Doors*1*(</text> <text>)*and*2* (</text> <text>)*closed,*for*temporary*installation*see</text> <text/>
问题原因
1. XPath表达式写法错误
你使用的text()/normalize-space()不符合XPath语法规范:/是轴分隔符,只能跟随节点轴或节点测试,而normalize-space()是函数,不能直接作为/的后续操作。
当前写法会被处理器解析为text()[normalize-space()],作用是过滤掉空白文本节点,而非对文本节点的内容执行normalize-space()(即压缩连续空格为单个空格)。这导致你在for-each中处理的仍是原始文本节点内容,而非预期的压缩后内容。
2. 正则表达式未匹配特殊空格(核心原因)
实际输出中2后仍有一个空格未被替换,大概率是因为该空格是非断行空格(U+00A0),而非普通空格(U+0020)。XSLT默认的正则表达式中,\s仅匹配[\t\n\f\r ](普通空格、制表符、换行等),不包含非断行空格。因此\s+只能匹配其中的普通空格,留下非断行空格,表现为未被替换的空格。
解决方案
- 修正XPath表达式:将
text()/normalize-space()改为遍历text()节点,在内部使用normalize-space(.)处理内容:<xsl:for-each select="text()"> <text><xsl:value-of select="normalize-space(.)"/></text> </xsl:for-each> - 若需匹配所有空白字符(包括非断行空格),修改正则表达式为
[\s\u00A0]+:<xsl:value-of select="replace(., '[\s\u00A0]+', '*')"/>
内容的提问来源于stack exchange,提问作者twfurst
相关产品推荐
相关产品推荐

