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

Posted

技术标签:

【中文标题】XSLT 访问和创建嵌套 xml 并将标签转换为属性【英文标题】:XSLT to access and create nested xml and convert tags to attributes 【发布时间】:2022-01-02 22:02:34 【问题描述】:

我有以下输入 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 表来做这个转换吗?

我尝试了类似下面的方法(未完成),实现这一目标的最佳方法是什么?解决方案应该在 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】:

如果您仅限于 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>

【讨论】:

这只是一个示例负载。谢谢你快速的回复。它正在工作,我可以得到预期的结果。

以上是关于XSLT 访问和创建嵌套 xml 并将标签转换为属性的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 XSLT 转换 XML

XSLT 如何从不同的标签级别访问属性?

在 Java 中通过 XSLT 进行 XML 粉碎

如何使用 xslt 将嵌套的 Json 对象转换为 xml

使用 XSLT 将 XML 转换为带有嵌套 AND/OR 的“布尔”英文句子

使用 Python 或 XSLT 将复杂的 XML 转换为 CSV