XSLT转换XML:移除特殊字符与波兰字符生成合法标签
解决XSLT转换中含特殊字符的属性名生成合法XML标签问题
核心思路
要处理含波兰特殊字符(ć、ż等)及非法符号(&、#等)的属性名,需通过字符归一化、非法字符移除、格式标准化三步生成合法XML标签名:
- 将波兰语特殊字符映射为对应的普通拉丁字符(如ć→c,ż→z)
- 移除所有非字母、数字、空格的非法字符
- 将空格替换为下划线,统一转为小写
XSLT 2.0+ 实现(推荐,代码更简洁)
XSLT 2.0及以上版本支持replace和lower-case函数,能快速实现清洗逻辑:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 保留你原有的所有转换逻辑 --> <!-- ... 原有代码片段 ... --> <!-- 自定义函数:清洗属性名生成合法标签名 --> <xsl:function name="local:clean-tag-name"> <xsl:param name="raw-name"/> <!-- 1. 替换波兰特殊字符为普通拉丁字符(覆盖大小写) --> <xsl:variable name="normalized-chars" select="translate($raw-name, 'ąćęłńóśźżĄĆĘŁŃÓŚŹŻ', 'acelnoszzACELNOSZZ')"/> <!-- 2. 移除所有非字母、数字、空格的字符 --> <xsl:variable name="stripped-illegal" select="replace($normalized-chars, '[^a-zA-Z0-9\s]', '')"/> <!-- 3. 替换空格为下划线,转为全小写 --> <xsl:value-of select="lower-case(replace($stripped-illegal, '\s+', '_'))"/> </xsl:function> <!-- 示例:处理带name属性的元素(根据你的原有逻辑调整匹配规则) --> <xsl:template match="*[@name]"> <!-- 使用清洗后的名称创建新标签 --> <xsl:element name="{local:clean-tag-name(@name)}"> <!-- 保留原有内容/属性的处理逻辑 --> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet>
XSLT 1.0 实现(兼容旧版处理器)
XSLT 1.0不支持自定义函数和replace,需用递归模板实现:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 保留你原有的所有转换逻辑 --> <!-- ... 原有代码片段 ... --> <!-- 递归模板:逐字符清洗属性名 --> <xsl:template name="clean-tag-name"> <xsl:param name="raw-name"/> <xsl:param name="processed" select="''"/> <xsl:if test="$raw-name != ''"> <xsl:variable name="current-char" select="substring($raw-name, 1, 1)"/> <!-- 替换波兰特殊字符 --> <xsl:variable name="normalized-char" select="translate($current-char, 'ąćęłńóśźżĄĆĘŁŃÓŚŹŻ', 'acelnoszzACELNOSZZ')"/> <xsl:choose> <!-- 保留字母、数字、空格 --> <xsl:when test="contains('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ', $normalized-char)"> <xsl:call-template name="clean-tag-name"> <xsl:with-param name="raw-name" select="substring($raw-name, 2)"/> <xsl:with-param name="processed" select="concat($processed, $normalized-char)"/> </xsl:call-template> </xsl:when> <!-- 移除其他非法字符 --> <xsl:otherwise> <xsl:call-template name="clean-tag-name"> <xsl:with-param name="raw-name" select="substring($raw-name, 2)"/> <xsl:with-param name="processed" select="$processed"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:if> <!-- 最后处理空格和大小写 --> <xsl:if test="$raw-name = ''"> <xsl:value-of select="translate(replace($processed, ' +', '_'), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/> </xsl:if> </xsl:template> <!-- 示例:处理带name属性的元素 --> <xsl:template match="*[@name]"> <xsl:variable name="clean-name"> <xsl:call-template name="clean-tag-name"> <xsl:with-param name="raw-name" select="@name"/> </xsl:call-template> </xsl:variable> <xsl:element name="{$clean-name}"> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet>
额外注意事项
- 如果原始属性名以数字开头,需在清洗后的名称前添加前缀(如
attr_),避免违反XML标签名规则 - 可根据需求调整合法字符范围,比如允许其他符号的话修改正则或
contains中的字符集 - 确保你的XSLT处理器支持对应版本:XSLT 2.0需要Saxon、Altova等处理器,XSLT 1.0兼容所有主流处理器
内容的提问来源于stack exchange,提问作者user20508390
相关产品推荐
相关产品推荐

