XSLT实现TYPE="NODE"条件下重命名XML标签的解决方案
XSLT实现XML节点按规则重命名方案
问题背景
需要对XML文档执行规则转换,现有实现仅能处理根节点,无法覆盖全量符合条件的节点。
待转换XML
<CONTENT> <DESCRIPTION TYPE="NODE"></DESCRIPTION> <DETAIL TYPE="NODE"></DETAIL> <DATA TYPE="NODE"> <ITEM DESC="ENTITY" VALUE="Y"></ITEM> <ITEM DESC="REQUEST" VALUE="Y"></ITEM> </DATA> </CONTENT>
转换规则
- 所有携带
TYPE="NODE"属性的元素(包含根元素CONTENT),标签名统一重命名为NODE - 重命名的节点新增
DESC属性,属性值为该元素的原始标签名,移除原有TYPE="NODE"属性 - 不满足条件的元素保持原有结构不变
预期输出
<NODE DESC="CONTENT"> <NODE DESC="DESCRIPTION"></NODE> <NODE DESC="DETAIL"></NODE> <NODE DESC="DATA"> <ITEM DESC="ENTITY" VALUE="Y"></ITEM> <ITEM DESC="REQUEST" VALUE="Y"></ITEM> </NODE> </NODE>
正确XSLT实现代码
<?xml version="1.0" encoding="UTF-8"?> <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:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <!-- 匹配所有需要重命名的节点:根CONTENT + 所有带TYPE="NODE"属性的元素 --> <xsl:template match="CONTENT | *[@TYPE='NODE']"> <NODE DESC="{name()}"> <!-- 复制除原TYPE属性外的其他属性,递归处理所有子节点 --> <xsl:apply-templates select="@*[name()!='TYPE'] | node()"/> </NODE> </xsl:template> </xsl:stylesheet>
原有代码问题说明
- 单独匹配
CONTENT节点的写法只能处理根元素,无法自动适配其他带TYPE="NODE"属性的子节点 - 属性判断语法错误:XSLT中读取属性必须加
@前缀,且需要判断的是TYPE属性而非DESC属性,正确的属性判断写法为@TYPE='NODE' - 采用通用匹配规则代替单节点硬编码匹配,可一次性覆盖所有符合条件的节点,后续新增同类型节点不需要修改XSLT代码
内容的提问来源于stack exchange,提问作者Somebody
相关产品推荐
相关产品推荐

