<...">

Delete the same node with the same attribute under the same parent in XML using xslt

I need to convert this XML input:

<root>
    <node id="a">
        <section id="a_1" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>

            </item>

            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>

            </item>
        </section>

        <section id="a_2" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>

            </item>
        </section>

    </node>

    <node id="b">
        <section id="b_1" method="create">
            <user id="b_1a" method="x">
                <attribute>

                    <origin>us</origin>
                </attribute>

            </user>
            <user id="b_1a" method="x">
                <attribute> 
                    <origin>us</origin>
                </attribute>
            </user>
            <user id="b_1b">
                <attribute>a</attribute>
            </user>
        </section>

        <section id="b_2">
            <user id="b_1a" method="x">
                <attribute>
                    <name>John</name>
                    <origin>us</origin>
                </attribute>
            </user>
        </section>
    </node>
</root>

Here is the expected result:

<root>
    <node id="a">
        <section id="a_1" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>                    
            </item>               
        </section>

        <section id="a_2" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>

            </item>
        </section>
    </node>

    <node id="b">
        <section id="b_1" method="create">
            <user id="b_1a" method="x">
                <attribute>
                    <origin>us</origin>
                </attribute>

            </user>

            <user id="b_1b">
                <attribute>a</attribute>
            </user>
        </section>

        <section id="b_2">
            <user id="b_1a" method="x">
                <attribute>
                    <name>John</name>
                    <origin>us</origin>
                </attribute>
            </user>
        </section>
    </node>
</root>

Note: a duplicate means that all children / children have the same value, a node can have 1 or more children if it is the same parent (id and method are the same), and we can assume that it is always in the same section ( id and method are the same).

can this be done? please enlighten me

Many thanks.

amuses John

+1
source share
1 answer

I. This is an XSLT 1.0 conversion :

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>

     <xsl:key name="kElemWithAttribs" match="*[@id and @method]"
      use="concat(generate-id(..), '+', name(), '+', @id, '+', @method)"/>

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

     <xsl:template match=
      "*[@id and @method
        and
         not(generate-id()
            =
             generate-id(key('kElemWithAttribs',
                             concat(generate-id(..),
                             '+',name(), '+', @id, '+', @method)
                             )[1]
                        )
             )
         ]"/>
</xsl:stylesheet>

when applied to the provided XML source document:

<root>
    <node id="a">
        <section id="a_1" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>
            </item>
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>
            </item>
        </section>
        <section id="a_2" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>
            </item>
        </section>
        <section id="a_2" method="run">
            <item id="0" method="a">
                <attribute>
                    <color>Red</color>
                    <status>1</status>
                    <condition>good</condition>
                </attribute>
            </item>
        </section>
    </node>
    <node id="b">
        <section id="b_1" method="create">
            <user id="b_1a" method="x">
                <attribute>
                    <origin>us</origin>
                </attribute>
            </user>
            <user id="b_1a" method="x">
                <attribute>
                    <origin>us</origin>
                </attribute>
            </user>
            <user id="b_1b">
                <attribute>a</attribute>
            </user>
        </section>
        <section id="b_2">
            <user id="b_1a" method="x">
                <attribute>
                    <name>John</name>
                    <origin>us</origin>
                </attribute>
            </user>
        </section>
    </node>
</root>

creates the desired, correct result:

<root>
   <node id="a">
      <section id="a_1" method="run">
         <item id="0" method="a">
            <attribute>
               <color>Red</color>
               <status>1</status>
               <condition>good</condition>
            </attribute>
         </item>
      </section>
      <section id="a_2" method="run">
         <item id="0" method="a">
            <attribute>
               <color>Red</color>
               <status>1</status>
               <condition>good</condition>
            </attribute>
         </item>
      </section>
   </node>
   <node id="b">
      <section id="b_1" method="create">
         <user id="b_1a" method="x">
            <attribute>
               <origin>us</origin>
            </attribute>
         </user>
         <user id="b_1b">
            <attribute>a</attribute>
         </user>
      </section>
      <section id="b_2">
         <user id="b_1a" method="x">
            <attribute>
               <name>John</name>
               <origin>us</origin>
            </attribute>
         </user>
      </section>
   </node>
</root>

. Muenchian , :

  • node "as-is".

  • xsl:key . , , , id, method ( ) , , id method.

  • , . , id, method ( ) ). , ( , "" ).

  • - 3. , , . , - , .


II. XSLT 2.0:

<xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

     <xsl:template match="*[@id]">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>

        <xsl:for-each-group select="*" group-by=
        "concat(generate-id(..), '+', name(), '+', @id, '+', @method)">
          <xsl:apply-templates select="."/>
        </xsl:for-each-group>
      </xsl:copy>
     </xsl:template>
</xsl:stylesheet>

. xsl:for-each-group group-by.

+2

All Articles