XSLT转换:CDATA转属性值时translate函数未生效问题排查
问题
需通过XSLT将XML文件转换为另一个XML文件,将指定元素的文本内容(包含换行)转换为属性,同时将换行符转换为
实体。
原XML片段:
<description> This is a description on more than one line </description>
期望转换结果:
<description value="This is a description on
 more than one line"/>
编写的XSLT代码如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:variable name="new-line" select="' '" /> <xsl:template name="writeParam" match="/"> <xsl:choose> <xsl:when test="description"> <xsl:element name="description"> <xsl:variable name="temp"> <xsl:value-of select="description"/> </xsl:variable> <xsl:attribute name="value"> <xsl:value-of select="translate($temp, $new-line, '
')" /> </xsl:attribute> </xsl:element> </xsl:when> </xsl:choose> </xsl:template> </xsl:stylesheet>
实际转换结果:
<description value=" This is a description on more than one line "/>
可见translate函数未生效,请问问题出在哪里?
解决方案
问题根源
- 换行符变量定义错误:在XSLT 1.0中,
select="' '"会将 解析为字符串 ,而非实际的换行符(ASCII 10字符)。这导致translate函数无法匹配到需要替换的换行符,自然不会执行替换操作。 - 首尾冗余换行未处理:原XML中
<description>标签首尾的换行被保留到了属性值中,不符合预期结果的格式。
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <!-- 定义实际的换行符:通过xsl:text输出真实的ASCII 10字符 --> <xsl:variable name="new-line"> <xsl:text> </xsl:text> </xsl:variable> <xsl:template match="/"> <xsl:if test="description"> <description> <xsl:attribute name="value"> <!-- 先去除文本首尾的空白(包括换行),再替换中间的换行符为
 --> <xsl:value-of select="translate(normalize-space(description), $new-line, '
')" /> </xsl:attribute> </description> </xsl:if> </xsl:template> </xsl:stylesheet>
关键修正说明
- 正确定义换行符:使用
<xsl:text> </xsl:text>定义new-line变量,确保变量存储的是实际的换行符(ASCII 10),而非字符串形式的 ,这样translate才能准确匹配并替换目标字符。 - 去除首尾冗余内容:
normalize-space()函数会自动去除文本首尾的空白(包括换行、空格、制表符),同时将中间的连续空白合并为单个空格。如果需要严格保留中间的空格结构,可改用substring结合string-length实现精准首尾修剪(适用于首尾仅各有一个换行的场景):<xsl:variable name="trimmed-text" select="substring(description, 2, string-length(description)-2)" /> <xsl:value-of select="translate($trimmed-text, $new-line, '
')" /> - 替换逻辑生效:当
new-line为实际换行符时,translate函数会将文本中的所有换行替换为
实体,最终输出符合预期的属性值。
内容的提问来源于stack exchange,提问作者Hervé Girod
相关产品推荐
相关产品推荐

