如何使用XSLT将XML文本节点中花括号内的数字转为下标?
问题描述
我有一个结构如下的XML文件:
<Chem> <Formula> CO{2} </Formula> <Name> Carbon Dioxide </Name> </Chem>
请问如何使用XSLT将花括号中的数字(或所有花括号内的数字)格式化为下标?
解决方案
XSLT 2.0及以上版本(简洁实现)
如果你的XSLT处理器支持2.0及以上版本,利用内置的replace正则替换函数就能快速完成需求:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 默认复制所有节点和文本 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 专门处理Formula元素内的文本 --> <xsl:template match="Formula/text()"> <!-- 匹配{数字}格式,替换为<sub>数字</sub> --> <xsl:value-of select="replace(., '\{(\d+)\}', '<sub>$1</sub>')" disable-output-escaping="yes"/> </xsl:template> </xsl:stylesheet>
- 核心逻辑:
replace(., '\{(\d+)\}', '<sub>$1</sub>')会捕获所有{数字}格式的内容,将数字部分包裹进<sub>标签;disable-output-escaping="yes"保证输出的是实际的HTML下标标签,而非转义后的字符实体。
XSLT 1.0版本(递归模板实现)
如果只能使用XSLT 1.0,需要通过递归模板来逐段处理文本:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 默认复制所有节点和文本 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 触发递归替换模板 --> <xsl:template match="Formula/text()"> <xsl:call-template name="replace-braces"> <xsl:with-param name="text" select="."/> </xsl:call-template> </xsl:template> <!-- 递归处理花括号内容的模板 --> <xsl:template name="replace-braces"> <xsl:param name="text"/> <xsl:choose> <xsl:when test="contains($text, '{')"> <!-- 输出花括号之前的文本 --> <xsl:value-of select="substring-before($text, '{')"/> <!-- 提取花括号内的数字 --> <xsl:variable name="target-num" select="substring-before(substring-after($text, '{'), '}')"/> <!-- 输出下标标签包裹的数字 --> <sub><xsl:value-of select="$target-num"/></sub> <!-- 递归处理剩余文本 --> <xsl:call-template name="replace-braces"> <xsl:with-param name="text" select="substring-after($text, '}')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <!-- 没有剩余花括号时直接输出文本 --> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
- 核心逻辑:通过递归遍历文本,每次定位到
{和}的位置,提取中间的数字并替换为<sub>标签,直到处理完所有匹配的花括号内容。
最终输出效果
处理后XML中的Formula节点内容会变为:
<Formula> CO<sub>2</sub> </Formula>
内容的提问来源于stack exchange,提问作者Mr. Mutant
相关产品推荐
相关产品推荐

