根据内部元素的 ID 将平面 xml 转换为树层次结构

Posted

技术标签:

【中文标题】根据内部元素的 ID 将平面 xml 转换为树层次结构【英文标题】:Converting a flat xml to a tree hierarchy based on IDs of inner elements 【发布时间】:2021-12-22 22:15:39 【问题描述】:

我的起始 XML 包含一个无序的平面目录列表,其中包含一个元素,每个元素都有自己的 ID 和子 ID(如果有的话)。

我的起始 XML 如下所示:

<root>

<catalogue>
    <item>
        <id>item2</id>
        <child>
            <id>item3</id>
        </child>
    </item>
</catalogue>

<catalogue>
    <item>
        <id>item1</id>
        <child>
            <id>item2</id>
        </child>
    </item>
</catalogue>

<catalogue>
    <item>
        <id>item3</id>
    </item>
</catalogue>

</root>

我需要将其转换为嵌套的树层次结构,其中相应的子项写入其父项内。

生成的 XML 应如下所示:

<root>

<catalogue>
    <item>
        <id>item1</id>
        <child>
            <id>item2</id>
        </child>
    </item>
    <catalogue>
        <item>
            <id>item2</id>
            <child>
                <id>item3</id>
            </child>
        </item>
        <catalogue>
            <item>
                <id>item3</id>
            </item>
        </catalogue>
    </catalogue>
</catalogue>

</root>

我已经有点接近解决方案了,但我无法让生成的 XML 文件不包含不必要的重复元素。

在以下 XML 文件中,根目录中的顶部和底部目录是重复的不需要的条目。我只需要大而中等的目录。

我当前的结果 XML 如下所示:

<root>

<catalogue>
    <item>
        <id>item2</id>
        <child>
            <id>item3</id>
        </child>
    </item>
    <catalogue>
        <item>
            <id>item3</id>
        </item>
    </catalogue>
</catalogue>

<catalogue>
    <item>
        <id>item1</id>
        <child>
            <id>item2</id>
        </child>
    </item>
    <catalogue>
        <item>
            <id>item2</id>
            <child>
                <id>item3</id>
            </child>
        </item>
        <catalogue>
            <item>
                <id>item3</id>
            </item>
        </catalogue>
    </catalogue>
</catalogue>

<catalogue>
    <item>
        <id>item3</id>
    </item>
</catalogue>

</root>

正在使用此 XSLT 文件创建我当前的结果 XML:

<xsl:stylesheet     version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="catalogue">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
        <xsl:for-each select="/root/catalogue[item/id/text() = current()/item/child/id/text()]">
            <xsl:apply-templates select="."/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

我一直试图找到解决这个问题的方法太久了,所以我希望有人能帮助我。

【问题讨论】:

【参考方案1】:

可能是这样的:

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:strip-space elements="*"/>

<xsl:key name="cat" match="catalogue" use="item/id" />

<xsl:template match="/root">
    <xsl:copy>
        <!-- start with items that are not children of any item -->
        <xsl:apply-templates select="catalogue[not(item/id = //child/id)]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="catalogue">
    <xsl:copy>
        <xsl:copy-of select="item"/>
        <!-- recurse with current item's children -->
        <xsl:apply-templates select="key('cat', item/child/id)"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

【讨论】:

以上是关于根据内部元素的 ID 将平面 xml 转换为树层次结构的主要内容,如果未能解决你的问题,请参考以下文章

尝试从 Excel 2013 批量导入到 TFS 时,如何将我的平面列表转换为树列表?

平面数组重组为树数组

数组转换为树树转换为数组

JS中树形对象与数组之间的相互转换

通过javascript将json转换为树数据

元素内部文本的 XML 文件转换?