通过保持使用XSLT中第一次出现删除重复的XML节点(Removing duplicate XML

2019-10-16 17:04发布

输入文件:

    <myroot>
        <nodeA id="a">
            <section id="i">  
                <item id="0" method="a"> <!-- parent section id="i" , keep this node-->
                    <somechild>a</somechild>
                </item>

                <item id="1" method="a">
                    <otherchild>a</otherchild>
                </item>
            </section>        

            <cell id="i">
                <part id="1" method="b"> <!-- parent cell id="i", keep this node-->
                    <attr>u</attr>
                </part>
            </cell>

            <section id="i">
                <item id="0" method="a"> <!-- parent section id="i", remove this node-->
                    <type>blah</type>
                </item>
                <item id="3" method="a">
                   <other>xx</other>    
                </item>

                <item id="0" method="b"> <!-- this has same id but different method, so we keep this -->
                    <otherchild>a</otherchild>
                </item>
            </section>

            <cell id="i">
                <part id="1" method="b"> <!-- parent cell id="i", remove this node -->
                    <attr>y</attr>
                </part>
            </cell>
        </nodeA>

        <nodeA id="b">
            <section id="i">
                <item id="1" method="a">
                    <otherchild>a</otherchild>
                </item>
            </section>        

            <section id="i">
                <item id="0" method="a">
                    <type>blah</type>
                </item>
                <item id="1" method="a">
                   <other>xx</other>    
                </item>
            </section>
           </nodeA>

        <nodeB id="a">
            <cell id="i">
                <part id="1" method="b">
                    <attr>u</attr>
                </part>
            </cell>

            <section id="i">
                <item id="0" method="a">
                    <type>blah</type>
                </item>                    
            </section>

            <cell id="i">
                <part id="1" method="b">
                    <attr>y</attr>
                </part>
            </cell>
        </nodeB>
</myroot>

输出:

<myroot>
        <nodeA id="a">
            <section id="i">
                <item id="0" method="a">
                    <somechild>a</somechild>
                </item>

                <item id="1" method="a">
                    <otherchild>a</otherchild>
                </item>
            </section>

            <cell id="i">
                <part id="1" method="b">
                    <attr>u</attr>
                </part>
            </cell>

            <section id="i">
                <item id="3" method="a">
                   <other>xx</other>    
                </item>

              <item id="0" method="b"> <!-- this has same id but different method, so we keep this -->
                    <otherchild>a</otherchild>
                </item>
                </section>
        </nodeA>

        <nodeA id="b">
            <section id="i">
                <item id="1" method="a">
                    <otherchild>a</otherchild>
                </item>
            </section>        

            <section id="i">
                <item id="0" method="a">
                    <type>blah</type>
                </item>
            </section>
           </nodeA>

        <nodeB id="a">
            <cell id="i">
                <part id="1" method="b">
                    <attr>u</attr>
                </part>
            </cell>

            <section id="i">
                <item id="0" method="a">
                    <type>blah</type>
                </item>                    
            </section>
        </nodeB>

</myroot>

谁能帮我改造,因此,如果一个节点出现两次或两次以上,并具有相同的父ID,我们只保留第一次出现,同时忽视其他。 也有在文件中另一元件即<nodeB></nodeB> <nodeC></nodeC> 。 等等。非常感谢。 约翰

Answer 1:

我认为你需要定义一键“组”的重复。 看来,他们是根据节点名称,@id和@method属性,父节点和@id分组。 因此,您将定义像这样的关键:

<xsl:key 
   name="duplicates" 
   match="*" 
    use="concat(local-name(), '|', @id, '|', @method, '|', local-name(..), '|', ../@id, '|', local-name(../..), '|', ../../@id)"/> 

然后,你需要忽略不是第一次在关键元素。 我想你也需要一个条款,只匹配是“孩子”元素的元素(否则谁部分内容将被忽略)

<xsl:template 
   match="*
      [@id!='']
      [not(.//*[@id!=''])]
      [generate-id() != generate-id(key('duplicates', concat(local-name(), '|', @id, '|', @method, '|', local-name(..), '|', ../@id, '|', local-name(../..), '|', ../../@id))[1])]/>

为了增加复杂性,它看起来像你不想,所有的子元素是重复的输出元素。

<xsl:template 
   match="*
     [@id!='']
     [.//*[@id!='']]
     [not(.//*
        [not(.//*[@id!=''])]
        [generate-id() = generate-id(key('duplicates', concat(local-name(), '|', @id, '|', @method, '|', local-name(..), '|', ../@id, '|', local-name(../..), '|', ../../@id))[1])])
     ]" />

试试下面的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
   <xsl:output method="xml" indent="yes"/> 
   <xsl:key name="duplicates" match="*" use="concat(local-name(), '|', @id, '|', @method, '|', local-name(..), '|', ../@id, '|', local-name(../..), '|', ../../@id)"/> 
   <xsl:template match="@*|node()"> 
      <xsl:copy> 
         <xsl:apply-templates select="@*|node()"/> 
      </xsl:copy> 
   </xsl:template> 
   <xsl:template match="*[@id!=''][not(.//*[@id!=''])][generate-id() != generate-id(key('duplicates', concat(local-name(), '|', @id, '|', @method, '|', local-name(..), '|', ../@id, '|', local-name(../..), '|', ../../@id))[1])]"/> 
   <xsl:template match="*[@id!=''][.//*[@id!='']][not(.//*[not(.//*[@id!=''])][generate-id() = generate-id(key('duplicates', concat(local-name(), '|', @id, '|', @method, '|', local-name(..), '|', ../@id, '|', local-name(../..), '|', ../../@id))[1])])]"/> 
</xsl:stylesheet> 

当应用到示例XML,下面是输出:

<myroot>
   <nodeA id="a">
      <section id="i">
         <item id="0" method="a"><!-- parent section id="i" , keep this node-->
            <somechild>a</somechild>
         </item>
         <item id="1" method="a">
            <otherchild>a</otherchild>
         </item>
      </section>
      <cell id="i">
         <part id="1" method="b"><!-- parent cell id="i", keep this node-->
            <attr>u</attr>
         </part>
      </cell>
      <section id="i">
         <item id="3" method="a">
            <other>xx</other>
         </item>
         <item id="0" method="b"><!-- this has same id but different method, so we keep this -->
            <otherchild>a</otherchild>
         </item>
      </section>
   </nodeA>
   <nodeA id="b">
      <section id="i">
         <item id="1" method="a">
            <otherchild>a</otherchild>
         </item>
      </section>
      <section id="i">
         <item id="0" method="a">
            <type>blah</type>
         </item>
      </section>
   </nodeA>
   <nodeB id="a">
      <cell id="i">
         <part id="1" method="b">
            <attr>u</attr>
         </part>
      </cell>
      <section id="i">
         <item id="0" method="a">
            <type>blah</type>
         </item>
      </section>
   </nodeB>
</myroot>


文章来源: Removing duplicate XML node by keeping the first occurence using XSLT
标签: xml xslt