XSLT 访问和创建嵌套 xml 并将标签转换为属性

XSLT to access and create nested xml and convert tags to attributes

我在下面输入 XML 消息,需要将其转换为具有多个属性的嵌套 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>

所有 S1、S2、S3 标签应保持原样,而其他子标签应作为属性添加到各自的父标签。嵌套 XML 数组的深度增加到 9,如 S1、S2、S3 ...S9。

我尝试编写 XSLT 转换并尝试使用递归函数,但我无法做到。有人可以帮我写一个 XSLT sheet 来做这个转换吗?

我尝试了类似下面的方法(未完成),实现此目的的最佳方法是什么?解决方案应该在 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" />
<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,那么这会很尴尬,因为需要区分 SuS3

但是,如果可以假设任何(且唯一)没有子元素的元素应该转换为属性,那么这可以简单而优雅地完成:

XSLT 1.0

<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="*[*]">
    <xsl:copy>
        <xsl:apply-templates select="*[not(*)]"/>
        <xsl:apply-templates select="*[*]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[not(*)]">
    <xsl:attribute name="{name()}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>