1
<LISTINGS>
<LISTING LISTING_ID="123456789">
    <NAME1>1</NAME1>
    <NAME1>1</NAME1>
    <NAME1>13</NAME1>
    <NAME1>13</NAME1>
    <NAME1>12</NAME1>
    <NAME1>100</NAME1>
    <NAME1>sumit is testing</NAME1>
    <NAME1>TEST IT</NAME1>
</LISTING>

<LISTING LISTING_ID="987654321">
    <NAME1>3</NAME1>
    <NAME1>3</NAME1>
    <NAME1>4</NAME1>
</LISTING>

<LISTING LISTING_ID="5656566565">
    <NAME1>3</NAME1>
    <NAME1>4</NAME1>
</LISTING>
</LISTINGS>

Output should be

<LISTINGS>
<LISTING LISTING_ID="123456789">
    <NAME1>1</NAME1>
    <NAME1>13</NAME1>
    <NAME1>12</NAME1>
    <NAME1>100</NAME1>
    <NAME1>sumit is testing</NAME1>
    <NAME1>TEST IT</NAME1>
</LISTING>

<LISTING LISTING_ID="987654321">
    <NAME1>3</NAME1>
    <NAME1>4</NAME1>
</LISTING>

<LISTING LISTING_ID="5656566565">
    <NAME1>3</NAME1>
    <NAME1>4</NAME1>
</LISTING>
</LISTINGS>
1
  • Good question, +1. See my answer for a demo of the Muenchian method for grouping -- short and efficient complete solution. Commented Dec 22, 2010 at 21:21

2 Answers 2

1

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kElementByListingIdAndValue"
             match="LISTING/*"
             use="concat(../@LISTING_ID,'+',.)"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="LISTING/*[count(.|key('kElementByListingIdAndValue',
                                               concat(../@LISTING_ID,
                                                      '+',
                                                      .)
                                              )[1]) != 1]"/>
</xsl:stylesheet>

Output:

<LISTINGS>
    <LISTING LISTING_ID="123456789">
        <NAME1>1</NAME1>
        <NAME1>13</NAME1>
        <NAME1>12</NAME1>
        <NAME1>100</NAME1>
        <NAME1>sumit is testing</NAME1>
        <NAME1>TEST IT</NAME1>
    </LISTING>
    <LISTING LISTING_ID="987654321">
        <NAME1>3</NAME1>
        <NAME1>4</NAME1>
    </LISTING>
    <LISTING LISTING_ID="5656566565">
        <NAME1>3</NAME1>
        <NAME1>4</NAME1>
    </LISTING>
</LISTINGS>
Sign up to request clarification or add additional context in comments.

Comments

1

Using the Muenchian method for grouping:

<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="kListNameByVal" match="LISTING/NAME1"
  use="concat(generate-id(..),'+',.)"/>

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

 <xsl:template match=
 "NAME1
   [not(generate-id()
       =
        generate-id(key('kListNameByVal',
                        concat(generate-id(..),'+',.)
                        )
                        [1]
                    )
        )
   ]
 "/>
</xsl:stylesheet>

when applied on the provided XML document:

<LISTINGS>
<LISTING LISTING_ID="123456789">
    <NAME1>1</NAME1>
    <NAME1>1</NAME1>
    <NAME1>13</NAME1>
    <NAME1>13</NAME1>
    <NAME1>12</NAME1>
    <NAME1>100</NAME1>
    <NAME1>sumit is testing</NAME1>
    <NAME1>TEST IT</NAME1>
</LISTING>

<LISTING LISTING_ID="987654321">
    <NAME1>3</NAME1>
    <NAME1>3</NAME1>
    <NAME1>4</NAME1>
</LISTING>

<LISTING LISTING_ID="5656566565">
    <NAME1>3</NAME1>
    <NAME1>4</NAME1>
</LISTING>
</LISTINGS>

the wanted, correct result is produced:

<LISTINGS>
   <LISTING LISTING_ID="123456789">
      <NAME1>1</NAME1>
      <NAME1>13</NAME1>
      <NAME1>12</NAME1>
      <NAME1>100</NAME1>
      <NAME1>sumit is testing</NAME1>
      <NAME1>TEST IT</NAME1>
   </LISTING>
   <LISTING LISTING_ID="987654321">
      <NAME1>3</NAME1>
      <NAME1>4</NAME1>
   </LISTING>
   <LISTING LISTING_ID="5656566565">
      <NAME1>3</NAME1>
      <NAME1>4</NAME1>
   </LISTING>
</LISTINGS>

4 Comments

can you point the meaning of [1] here? I always thought that generate-id(), applied to a key, will always generate id of the first element, that matches key pattern. Also, your code works well without this predicate.
@Flack: Muenchian method selects first in a kind, that's why you have to compare the node (in this case with the generate-id()) with the first one (in document order) node with the same key.
@Alejandro, thanks, I've got the point. Still, can you provide a link with an example, where necessity is more obvious. I just want to consolidate the knowledge a little bit.
@Flack: Yes, but I always write [1] to make this fact absolutely clear. Many people forget or don't know the fact that when the argument of generate-id() is a node-set, the it takes only the first node, in document order, from that node-set. Exactly the same as <xsl:value-of>.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.