多级XSLT分组并消除最后一级的重复

时间:2017-12-13 15:43:30

标签: xml xslt

我有STM32CubeMX以GPDSC格式生成的项目,我想将其转换为Netbeans C项目。幸运的是,两者都是XML,所以我编写了XSL转换。

我正在对<modules runAllManagedModulesForAllRequests="true"> <!-- ... --> </modules> 进行分组,然后按component/@Cclass进行分组,然后我想在此组中打印所有不同的component/@Cgroup

以下是源XML示例:

file/@name

这是我的XSL转换

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<package>
<components>
    <component Cclass="CMSIS" Cgroup="CORE">
    <files>
        <file name="core_cm0.h"/>
    </files>
    </component>
    <component Cclass="Device" Cgroup="Startup">  
    <files>
        <file name="stm32f0xx.h"/>
    </files>
    </component>
    <component Cclass="Device" Cgroup="STM32Cube HAL" Csub="USART">
    <files>
        <file name="stm32f0xx_ll_usart.h"/>
        <file name="stm32f0xx_ll_rcc.h"/>
    </files>
    </component>
    <component Cclass="Device" Cgroup="STM32Cube HAL" Csub="RCC">
    <files>
        <file name="stm32f0xx_ll_cortex.h"/>
        <file name="stm32f0xx_ll_rcc.h"/>
    </files>
    </component>
</components>
</package>

这是输出XML:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes"/> 

<xsl:key name="k1" match="component" use="@Cclass"/>
<xsl:key name="k2" match="component" use="concat(@Cclass, '|', @Cgroup)"/>
<xsl:key name="k3" match="file" use="@name"/>

<xsl:template name="file-classes" match="components">
    <xsl:for-each select="component[generate-id() = generate-id(key('k1', @Cclass)[1])]">
        <logicalFolder projectFiles="true">
        <xsl:attribute name="displayName"><xsl:value-of select="@Cclass" /></xsl:attribute>
        <xsl:for-each select="key('k1', @Cclass)[generate-id() = generate-id(key('k2', concat(@Cclass, '|', @Cgroup))[1])]">
            <logicalFolder projectFiles="true">
            <xsl:attribute name="displayName"><xsl:value-of select="@Cgroup" /></xsl:attribute>
            <xsl:for-each select="key('k2', concat(@Cclass, '|', @Cgroup))">
                <xsl:for-each select="files/file[generate-id() = generate-id(key('k3', @name)[1])]">
                    <xsl:sort select="@name" />
                    <xsl:for-each select="key('k3', @name)">
                        <itemPath><xsl:value-of select="@name" /></itemPath>
                    </xsl:for-each>
                </xsl:for-each>
            </xsl:for-each>
            </logicalFolder>
        </xsl:for-each>
        </logicalFolder>
    </xsl:for-each>
</xsl:template>

<xsl:template match="/">
    <xsl:for-each select="package/components">
    <xsl:call-template name="file-classes"/>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

正如您所看到的,两个级别的分组有效,但我有重复的<?xml version="1.0" encoding="utf-8"?> <logicalFolder projectFiles="true" displayName="CMSIS"> <logicalFolder projectFiles="true" displayName="CORE"> <itemPath>core_cm0.h</itemPath> </logicalFolder> </logicalFolder> <logicalFolder projectFiles="true" displayName="Device"> <logicalFolder projectFiles="true" displayName="Startup"> <itemPath>stm32f0xx.h</itemPath> </logicalFolder> <logicalFolder projectFiles="true" displayName="STM32Cube HAL"> <itemPath>stm32f0xx_ll_rcc.h</itemPath> <itemPath>stm32f0xx_ll_rcc.h</itemPath> <itemPath>stm32f0xx_ll_usart.h</itemPath> <itemPath>stm32f0xx_ll_cortex.h</itemPath> </logicalFolder> </logicalFolder> 个节点,因为在源XML中,有多个itemPath个节点多次,例如file

如何删除重复项?我在第三级分组上有点迷失。

1 个答案:

答案 0 :(得分:0)

我相信你只需要处理第一次出现的“k3”组。

所以改变:

<xsl:for-each select="key('k3', @name)">

为:

<xsl:for-each select="key('k3', @name)[1]">