XSLT匹配同名标签元素:动态重命名子元素技术需求
解决方案:动态修改重复元素的标签名(无需预设元素名)
我特意写了一个完全通用的XSLT方案,不需要预先知晓任何元素名称,能根据输入动态处理,完美匹配你要的场景:
<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="*"> <!-- 新标签名 = 原元素本地名称 + 第一个属性的值 --> <xsl:element name="{local-name()}{@*[1]}"> <!-- 复制原元素的所有属性 --> <xsl:apply-templates select="@*"/> <!-- 递归处理子节点 --> <xsl:apply-templates select="node()"/> </xsl:element> </xsl:template> </xsl:stylesheet>
代码细节解释
- 默认复制模板:确保除了需要修改的元素标签名之外,其他所有内容(属性、文本、注释等)都原样保留,保证XML结构的完整性。
- 核心元素处理模板:
{local-name()}:获取当前元素的本地标签名(自动忽略命名空间,适配更复杂的XML场景){@*[1]}:精准获取当前元素的第一个属性的值,不管属性叫什么名字都能生效<xsl:element>:动态创建新的元素节点,把原标签名和属性值拼接成新标签
测试示例验证
示例1输入:
<Elem1> <Obj name="1"> <Obj name="2"> <Obj name="3"> </Obj> </Obj> </Obj> </Elem1>
示例1输出:
<Elem1> <Obj1 name="1"> <Obj2 name="2"> <Obj3 name="3"> </Obj3> </Obj2> </Obj1> </Elem1>
示例2输入:
<Elem1> <Second name="1"> <Second name="2"> <Second name="3"> </Second> </Second> </Second> </Elem1>
示例2输出:
<Elem1> <Second1 name="1"> <Second2 name="2"> <Second3 name="3"> </Second3> </Second2> </Second1> </Elem1>
扩展适配(可选)
如果你的场景中存在没有属性的元素,可以给模板加个判断,让无属性元素保持原标签名:
<xsl:template match="*"> <xsl:choose> <xsl:when test="@*"> <xsl:element name="{local-name()}{@*[1]}"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:template>
内容的提问来源于stack exchange,提问作者RaduSR
相关产品推荐
相关产品推荐

