使用XSLT替换XML节点名Unicode转义符并重构目标节点结构
解决方法
核心思路
- XSLT 1.0 没有内置全局字符串替换函数,因此需要自定义递归模板实现子串替换功能
- 嵌套调用替换模板即可支持多种Unicode转义序列的批量还原
- 在重构节点结构的同时直接对节点名调用替换模板,一步完成两项需求
调整后完整代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="namespace/url"> <xsl:key name="elements" match="*" use="name()"/> <!-- 通用递归替换模板 --> <xsl:template name="recursive-replace"> <xsl:param name="input"/> <xsl:param name="target"/> <xsl:param name="replace"/> <xsl:choose> <xsl:when test="contains($input, $target)"> <xsl:value-of select="substring-before($input, $target)"/> <xsl:value-of select="$replace"/> <xsl:call-template name="recursive-replace"> <xsl:with-param name="input" select="substring-after($input, $target)"/> <xsl:with-param name="target" select="$target"/> <xsl:with-param name="replace" select="$replace"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$input"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="/"> <ns2:result> <ns2:reference_list> <xsl:for-each select="result/reference_list/*[generate-id(.)=generate-id(key('elements',name())[1])]"> <xsl:sort select="name()"/> <xsl:for-each select="key('elements', name())"> <xsl:if test="position()=1"> <ns2:department> <ns2:name> <!-- 按顺序替换所有Unicode转义序列,可按需扩展更多规则 --> <xsl:variable name="spaceReplaced"> <xsl:call-template name="recursive-replace"> <xsl:with-param name="input" select="name()"/> <xsl:with-param name="target" select="'__u0020'"/> <xsl:with-param name="replace" select="' '"/> </xsl:call-template> </xsl:variable> <xsl:call-template name="recursive-replace"> <xsl:with-param name="input" select="$spaceReplaced"/> <xsl:with-param name="target" select="'__u0026'"/> <xsl:with-param name="replace" select="'&'"/> </xsl:call-template> </ns2:name> <ns2:id> <xsl:value-of select="current()"/> </ns2:id> </ns2:department> </xsl:if> </xsl:for-each> </xsl:for-each> </ns2:reference_list> </ns2:result> </xsl:template> </xsl:stylesheet>
补充说明
如果你的运行环境支持XSLT 2.0及以上版本,可以不用自定义递归模板,直接调用内置replace函数即可,代码更简洁:
<ns2:name> <xsl:value-of select="replace(replace(name(), '__u0020', ' '), '__u0026', '&')"/> </ns2:name>
内容的提问来源于stack exchange,提问作者Reinout
相关产品推荐
相关产品推荐

