You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用XSLT 1.0实现XML子标签转属性并保留Sx层级嵌套

XML报文转换需求

需要将输入XML转换为带多属性的嵌套XML结构,转换规则如下:

  • 所有S1、S2、S3直至S9层级的标签原样保留为元素
  • 其余子标签需转换为对应父级S标签的属性
  • 嵌套深度最高可达9层(S1到S9)

输入XML示例

<S1>
    <P>23432</P>
    <Su>BG</Su>
    <S2>
        <P>cc</P>
        <Su>B</Su>
        <S3>
            <P>427013947</P>
            <Su>RM</Su>
            <F>MDF</F>
            <I>427113948</I>
            <C>true</C>
            <T></T>
            <A>xxx</A>
        </S3>
        <F></F>
        <I>427013947</I>
        <C>true</C>
        <T></T>
        <A>xxxsx</A>
    </S2>
    <S2>
        <P>cc</P>
        <Su>FL</Su>
        <F>1</F>
        <I>427814536</I>
        <C>true</C>
        <T></T>
        <A>xxxsx</A>
    </S2>
    <S2>
        <P>cc</P>
        <Su>G</Su>
        <F></F>
        <I>444</I>
        <C>true</C>
        <T></T>
        <A>xxxsx</A>
    </S2>
    <F>1</F>
    <I>cc</I>
    <C>true</C>
    <T></T>
    <A>xxxs</A>
    <B></B>
</S1>

期望输出XML示例

<S1 P="23432" Su="BG" F="1" I="cc" C="true" T="" A="xxxs" B="">
    <S2 P="cc" Su="B" F="" I="427013947" C="true" T="" A="xxxsx">
        <S3 P="427013947" Su="RM" F="MDF" I="427113948" C="true" T="" A="xxx"></S3>
    </S2>
    <S2 P="cc" Su="FL" F="1" I="427814536" C="true" T="" A="xxxsx"></S2>
    <S2 P="cc" Su="G" F="" I="444" C="true" T="" A="xxxsx"></S2>
</S1>

现有未完成的XSLT代码

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="//S1">
    <xsl:element name="S1">
        <xsl:for-each select="*">
            <xsl:if test="local-name()!='S1'">
                <xsl:attribute name="{name()}" >
                    <xsl:value-of select="text()" />
                </xsl:attribute>
            </xsl:if>
        </xsl:for-each>
        <xsl:for-each select="S2">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:for-each>
    </xsl:element>
</xsl:template></xsl:stylesheet>
XSLT 1.0 转换脚本实现

以下是符合需求的完整转换代码:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" encoding="UTF-8" />
    <!-- 匹配S1~S9所有层级节点 -->
    <xsl:template match="*[starts-with(name(), 'S') and string-length(name())=2 and substring(name(),2,1) >= '1' and substring(name(),2,1) <= '9']">
        <xsl:element name="{name()}">
            <!-- 转换非S层级子节点为属性 -->
            <xsl:for-each select="*[not(starts-with(name(), 'S') and string-length(name())=2 and substring(name(),2,1) >= '1' and substring(name(),2,1) <= '9')]">
                <xsl:attribute name="{name()}">
                    <xsl:value-of select="text()" />
                </xsl:attribute>
            </xsl:for-each>
            <!-- 递归处理子级S节点 -->
            <xsl:apply-templates select="*[starts-with(name(), 'S') and string-length(name())=2 and substring(name(),2,1) >= '1' and substring(name(),2,1) <= '9']" />
        </xsl:element>
    </xsl:template>
    <!-- 过滤原XML中的空白文本节点 -->
    <xsl:template match="text()" />
</xsl:stylesheet>

实现逻辑说明

  1. 节点匹配规则通过「名称以S开头、长度为2、第二个字符为1-9的数字」三个条件精准命中S1到S9所有层级的节点,无需为每个S层级单独写模板
  2. 对每个命中的S层级节点,先遍历所有非S层级的子节点,将标签名作为属性名、文本内容作为属性值挂载到当前S节点上
  3. 递归应用模板处理当前节点下的子S层级节点,自动支持最高9层的嵌套转换
  4. 空白文本节点匹配规则用来过滤原XML中的缩进、换行等无效内容,保证输出格式整洁

内容的提问来源于stack exchange,提问作者Dil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 08:54:05