层次结构转换中的 XSLT 重复项

XSLT duplicate items in a hierarchy transfomation

我是论坛的新人所以请原谅我的一些风格和语言不是英语的错误。 我的问题是我在数据库上的 select 中有一个 xml 的输出,我想通过 xslt 将这种平面结构转换为层次结构。 我的 xslt 工作正常,层次结构正确,但存在一个问题,即复制所有项目并使其复制根元素 这是数据库 select 的 xml 输出:

<cdcDbSet xmlns="http://eos.mcr.com/cdc/anagrafica/ds">
   <cdcEntity>
      <idCdc>17</idCdc>
      <idCdcParent>5</idCdcParent>
      <cdcName>testGP</cdcName>
      <order>1</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>15</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Caserta</cdcName>
      <order>1</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>5</idCdc>
      <idCdcParent>2</idCdcParent>
      <cdcName>Progetti</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>16</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>testGP</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>18</idCdc>
      <idCdcParent>5</idCdcParent>
      <cdcName>testGPS</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>11</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>figlio</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>10</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>pippo</cdcName>
      <order>3</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>6</idCdc>
      <idCdcParent>5</idCdcParent>
      <cdcName>EOS</cdcName>
      <order>3</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>3</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Milano</cdcName>
      <order>4</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>7</idCdc>
      <idCdcParent>3</idCdcParent>
      <cdcName>l</cdcName>
      <order>4</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>14</idCdc>
      <idCdcParent>15</idCdcParent>
      <cdcName>testMOD</cdcName>
      <order>4</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>8</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>pippo</cdcName>
      <order>5</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>4</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Napoli</cdcName>
      <order>5</order>
      <isUsed>false</isUsed>
   </cdcEntity>
   <cdcEntity>
      <idCdc>9</idCdc>
      <idCdcParent>4</idCdcParent>
      <cdcName>cccc</cdcName>
      <order>6</order>
      <isUsed>false</isUsed>
   </cdcEntity>
</cdcDbSet>

这是 xslt:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:nsc="http://eos.mcr.com/cdc/anagrafica/ds" version="1.0">
<xsl:key match="/nsc:cdcDbSet/nsc:cdcEntity" name="nodeChildren" use="nsc:idCdcParent"/>
<xsl:variable name="root" select="/nsc:cdcDbSet/nsc:cdcEntity/nsc:idCdcParent"/>
<xsl:template match="nsc:cdcDbSet">
    <cdcList xmlns="http://ws.apache.org/ns/synapse">
        <xsl:apply-templates select="nsc:cdcEntity[nsc:idCdcParent=$root]"/>
    </cdcList>
</xsl:template>
<xsl:template match="nsc:cdcEntity">
    <cdc xmlns="http://ws.apache.org/ns/synapse">
        <idCdc>
            <xsl:value-of select="nsc:idCdc"/>
        </idCdc>
        <idCdcParent>
            <xsl:value-of select="nsc:idCdcParent"/>
        </idCdcParent>
        <cdcName>
            <xsl:value-of select="nsc:cdcName"/>
        </cdcName>
        <order>
            <xsl:value-of select="nsc:order"/>
        </order>
        <isUsed>
            <xsl:value-of select="nsc:isUsed"/>
        </isUsed>
        <cdcList>
            <xsl:apply-templates select="key('nodeChildren',nsc:idCdc)"/>
        </cdcList>
    </cdc>
</xsl:template>
</xsl:stylesheet>

这是转换后的 xml :

<cdcList xmlns="http://ws.apache.org/ns/synapse"
         xmlns:nsc="http://eos.mcr.com/cdc/anagrafica/ds">
   <cdc>
      <idCdc>17</idCdc>
      <idCdcParent>5</idCdcParent>
      <cdcName>testGP</cdcName>
      <order>1</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>15</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Caserta</cdcName>
      <order>1</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>14</idCdc>
            <idCdcParent>15</idCdcParent>
            <cdcName>testMOD</cdcName>
            <order>4</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
   <cdc>
      <idCdc>5</idCdc>
      <idCdcParent>2</idCdcParent>
      <cdcName>Progetti</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>17</idCdc>
            <idCdcParent>5</idCdcParent>
            <cdcName>testGP</cdcName>
            <order>1</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
         <cdc>
            <idCdc>18</idCdc>
            <idCdcParent>5</idCdcParent>
            <cdcName>testGPS</cdcName>
            <order>2</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
         <cdc>
            <idCdc>6</idCdc>
            <idCdcParent>5</idCdcParent>
            <cdcName>EOS</cdcName>
            <order>3</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
   <cdc>
      <idCdc>16</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>testGP</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>18</idCdc>
      <idCdcParent>5</idCdcParent>
      <cdcName>testGPS</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>11</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>figlio</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>10</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>pippo</cdcName>
      <order>3</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>6</idCdc>
      <idCdcParent>5</idCdcParent>
      <cdcName>EOS</cdcName>
      <order>3</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>3</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Milano</cdcName>
      <order>4</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>7</idCdc>
            <idCdcParent>3</idCdcParent>
            <cdcName>l</cdcName>
            <order>4</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
   <cdc>
      <idCdc>7</idCdc>
      <idCdcParent>3</idCdcParent>
      <cdcName>l</cdcName>
      <order>4</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>14</idCdc>
      <idCdcParent>15</idCdcParent>
      <cdcName>testMOD</cdcName>
      <order>4</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>8</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>pippo</cdcName>
      <order>5</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>4</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Napoli</cdcName>
      <order>5</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>9</idCdc>
            <idCdcParent>4</idCdcParent>
            <cdcName>cccc</cdcName>
            <order>6</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
   <cdc>
      <idCdc>9</idCdc>
      <idCdcParent>4</idCdcParent>
      <cdcName>cccc</cdcName>
      <order>6</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>

如您所见,有些项目是重复的,我想将其删除。 例如,idCdc=17 的项目 cdc 在 cdcList 下,在 idCdc=5 的 cdc 下 我曾尝试修改 xslt,但没有取得好结果。 谢谢大家帮助我。

P.s.: 我希望看到这样的东西 :

    <cdcList xmlns="http://ws.apache.org/ns/synapse" xmlns:nsc="http://eos.mcr.com/cdc/anagrafica/ds">
   <cdc>
      <idCdc>1</idCdc>
      <idCdcParent>0</idCdcParent>
      <cdcName>Roma</cdcName>
      <order>1</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>4</idCdc>
            <idCdcParent>1</idCdcParent>
            <cdcName>testMOD</cdcName>
            <order>4</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
         <cdc>
            <idCdc>5</idCdc>
            <idCdcParent>1</idCdcParent>
            <cdcName>testMOD</cdcName>
            <order>4</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
         <cdc>
            <idCdc>6</idCdc>
            <idCdcParent>1</idCdcParent>
            <cdcName>testMOD</cdcName>
            <order>4</order>
            <isUsed>false</isUsed>
            <cdcList>
                <cdc>
                    <idCdc>7</idCdc>
                    <idCdcParent>6</idCdcParent>
                    <cdcName>testMODChild</cdcName>
                    <order>4</order>
                    <isUsed>false</isUsed>
                    <cdcList/>
                </cdc>
            </cdcList>
         </cdc>
      </cdcList>
   </cdc>
   <cdc>
      <idCdc>2</idCdc>
      <idCdcParent>0</idCdcParent>
      <cdcName>Progetti</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>8</idCdc>
            <idCdcParent>2</idCdcParent>
            <cdcName>testGP</cdcName>
            <order>1</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
         <cdc>
            <idCdc>9</idCdc>
            <idCdcParent>2</idCdcParent>
            <cdcName>testGPS</cdcName>
            <order>2</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
         <cdc>
            <idCdc>10</idCdc>
            <idCdcParent>2</idCdcParent>
            <cdcName>EOS</cdcName>
            <order>3</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
   <cdc>
      <idCdc>3</idCdc>
      <idCdcParent>0</idCdcParent>
      <cdcName>Milano</cdcName>
      <order>4</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>11</idCdc>
            <idCdcParent>3</idCdcParent>
            <cdcName>l</cdcName>
            <order>4</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
</cdcList>

你的错误在这里:

<xsl:variable name="root" select="/nsc:cdcDbSet/nsc:cdcEntity/nsc:idCdcParent"/>

这不是select单个节点,更不是根节点,甚至是根节点的ID。

它selects 所有 <nsc:idCdcParent>个元素。连同这个

<xsl:apply-templates select="nsc:cdcEntity[nsc:idCdcParent=$root]"/>

其中 [nsc:idCdcParent=$root] 始终为真,因为所有 <nsc:idCdcParent> 都在 $root 中,并且递归步骤

<xsl:apply-templates select="key('nodeChildren',nsc:idCdc)"/>

您多次浏览输入文档,导致输出重复。


假设根节点的 ID 为 1,这将生成一个正确嵌套的树。

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:nsc="http://eos.mcr.com/cdc/anagrafica/ds"
    xmlns="http://ws.apache.org/ns/synapse"
    exclude-result-prefixes="nsc"
>
    <xsl:output indent="yes" />
    <xsl:key name="nodesByParent" match="nsc:cdcEntity" use="nsc:idCdcParent"/>

    <xsl:template match="nsc:cdcDbSet">
        <cdcList>
            <xsl:apply-templates select="key('nodesByParent', 1)"/>
        </cdcList>
    </xsl:template>

    <xsl:template match="nsc:cdcEntity">
        <cdc>
            <xsl:apply-templates mode="copy-local" select="
                nsc:idCdc|nsc:idCdcParent|nsc:cdcName|nsc:order|nsc:isUsed
            " />
            <cdcList>
                <xsl:apply-templates select="key('nodesByParent', nsc:idCdc)"/>
            </cdcList>
        </cdc>
    </xsl:template>

    <xsl:template match="*" mode="copy-local">
        <xsl:element name="{local-name()}">
            <xsl:value-of select="." />
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

备注

  • 顶级默认xmlns声明,因此您无需在样式表正文中重复自己
  • exclude-result-prefixes 属性
  • 通过使用模板输出具有相同本地名称的任何元素减少了重复

结果:

<cdcList xmlns="http://ws.apache.org/ns/synapse">
   <cdc>
      <idCdc>15</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Caserta</cdcName>
      <order>1</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>14</idCdc>
            <idCdcParent>15</idCdcParent>
            <cdcName>testMOD</cdcName>
            <order>4</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
   <cdc>
      <idCdc>16</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>testGP</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>11</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>figlio</cdcName>
      <order>2</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>10</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>pippo</cdcName>
      <order>3</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>3</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Milano</cdcName>
      <order>4</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>7</idCdc>
            <idCdcParent>3</idCdcParent>
            <cdcName>l</cdcName>
            <order>4</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
   <cdc>
      <idCdc>8</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>pippo</cdcName>
      <order>5</order>
      <isUsed>false</isUsed>
      <cdcList/>
   </cdc>
   <cdc>
      <idCdc>4</idCdc>
      <idCdcParent>1</idCdcParent>
      <cdcName>Napoli</cdcName>
      <order>5</order>
      <isUsed>false</isUsed>
      <cdcList>
         <cdc>
            <idCdc>9</idCdc>
            <idCdcParent>4</idCdcParent>
            <cdcName>cccc</cdcName>
            <order>6</order>
            <isUsed>false</isUsed>
            <cdcList/>
         </cdc>
      </cdcList>
   </cdc>
</cdcList>

这个转换工作得很好,但是如果我想要一个没有 cdc 项并且在每个 cdcList 中都有方括号的输出,就像这个一样?

{
"cdcList": [{
        "idCdc": 2,
        "idCdcParent": null,
        "cdcName": "Roma",
        "order": 1,
        "isUsed": false,
        "cdcList": [{
            "idCdc": 5,
            "idCdcParent": 2,
            "cdcName": "Progetti",
            "order": 2,
            "isUsed": false,
            "cdcList": [{
                    "idCdc": 17,
                    "idCdcParent": 5,
                    "cdcName": "testGP",
                    "order": 1,
                    "isUsed": false,
                    "cdcList": null
                },
                {
                    "idCdc": 18,
                    "idCdcParent": 5,
                    "cdcName": "testGPS",
                    "order": 2,
                    "isUsed": false,
                    "cdcList": null
                }
            ]



        }]
    },
    {
        "idCdc": 3,
        "idCdcParent": null,
        "cdcName": "Milano",
        "order": 4,
        "isUsed": false,
        "cdcList": [{

            "idCdc": 7,
            "idCdcParent": 3,
            "cdcName": "l",
            "order": 4,
            "isUsed": false,
            "cdcList": null
        }]
    },
    {
        "idCdc": 4,
        "idCdcParent": null,
        "cdcName": "Napoli",
        "order": 5,
        "isUsed": false,
        "cdcList": [{

            "idCdc": 9,
            "idCdcParent": 4,
            "cdcName": "cccc",
            "order": 6,
            "isUsed": false,
            "cdcList": null
        }]
    }
]

}

我需要在 Angular5 中实现这个 json 并且树组件库需要这种格式的输出