如何用XSLT动态生成元素名并按下划线分组转换XML
解决动态下划线元素名的多层分组XML转换问题
嘿,我完全懂你作为XSLT新手的困扰——面对这种全是下划线分隔的动态元素名,硬编码肯定行不通,用substring也没法处理多层嵌套的分组。咱们换个思路,用递归模板配合tokenize()函数来搞定这个动态层级问题,完美适配你的需求!
完整XSLT解决方案
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 匹配根节点,生成新的<data>根元素 --> <xsl:template match="/data"> <data> <!-- 按元素名的第一个下划线前缀分组(比如fruits、animal) --> <xsl:for-each-group select="*" group-by="tokenize(local-name(), '_')[1]"> <!-- 动态创建分组的顶层元素 --> <xsl:element name="{current-grouping-key()}"> <!-- 调用递归模板处理每个元素的剩余名称片段 --> <xsl:apply-templates select="current-group()"> <xsl:with-param name="remaining-parts" select="tokenize(local-name(), '_')[position() > 1]"/> </xsl:apply-templates> </xsl:element> </xsl:for-each-group> </data> </xsl:template> <!-- 递归核心模板:处理剩余的名称片段,自动生成嵌套元素 --> <xsl:template match="*"> <xsl:param name="remaining-parts" as="xs:string*"/> <!-- 情况1:只剩最后一个片段,直接创建元素并赋值 --> <xsl:if test="count($remaining-parts) = 1"> <xsl:element name="{$remaining-parts[1]}"> <xsl:value-of select="."/> </xsl:element> </xsl:if> <!-- 情况2:还有多个片段,继续按当前第一个片段分组 --> <xsl:if test="count($remaining-parts) > 1"> <xsl:for-each-group select="." group-by="$remaining-parts[1]"> <xsl:element name="{current-grouping-key()}"> <!-- 递归调用,传递去掉第一个片段后的剩余部分 --> <xsl:apply-templates select="current-group()"> <xsl:with-param name="remaining-parts" select="$remaining-parts[position() > 1]"/> </xsl:apply-templates> </xsl:element> </xsl:for-each-group> </xsl:if> </xsl:template> </xsl:stylesheet>
关键逻辑解释
- 初始分组:在根模板里,用
tokenize(local-name(), '_')把每个元素名拆分成下划线分隔的片段,然后按第一个片段(比如fruits、animal)分组,自动生成顶层的<fruits>、<animal>元素。 - 递归嵌套:递归模板是核心——每次接收剩余的名称片段,判断剩余数量:
- 如果只剩1个片段,直接创建元素并填入原元素的数值;
- 如果还有多个片段,继续按当前第一个片段分组,创建父元素后递归处理剩下的片段,自动生成多层嵌套结构。
- 完全动态适配:全程用
xsl:element动态生成元素名,不需要硬编码任何层级的名称,不管你的真实数据有多少层下划线分隔,都能自动生成对应的嵌套XML。
注意事项
- 这个方案需要你的XSLT处理器支持XSLT 2.0或更高版本(比如Saxon、Altova XMLSpy,或者一些现代在线XSLT工具);
- 把你的示例数据输入进去,运行这个XSLT就能得到你期望的输出结果,完全匹配需求。
内容的提问来源于stack exchange,提问作者maverick
相关产品推荐
相关产品推荐

