xsl-list
[Top] [All Lists]

Determining uniqueness based on mulitple element values

2002-12-13 12:33:49
Hi all,

I hope this doesn't further the decline in the quality of the questions
on xsl list too much, but here goes:
I've got xml that contains large lists of things.  The uniqueness of an
item in the list is defined by the contents
of more than one child element.  What I want to do is to create a table
of all of the unique items in the list.

So, for example, in a list of cars at auto dealerships, for each dealer,
I want to list the unique cars, where
unique is defined by the contents of all of <make> <model> and <year>:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="c:\myprojects\testdata\xslfiles\testfile.xsl"
type="text/xsl"?>
<carlist>
 <dealership name="Fred's Used Cars">
  <car>
   <make>Chevy</make>
   <model>Malibu</model>
   <year>1979</year>
  </car>
  <car>
   <make>Dodge</make>
   <model>Charger</model>
   <year>1979</year>
  </car>
  <!-- This one should get filtered out, because it is the same as the
first car in this dealers list-->
  <car>
   <make>Chevy</make>
   <model>Malibu</model>
   <year>1979</year>
  </car>
 </dealership>
 <dealership name="Best in Town Cars">
  <!-- This one should not get filtered out, because it is the only one
in this dealers list -->
  <car>
   <make>Chevy</make>
   <model>Malibu</model>
   <year>1979</year>
  </car>
  <car>
   <make>Chevy</make>
   <model>Caprice</model>
   <year>1997</year>
  </car>
  <car>
   <make>Buick</make>
   <model>Skylark</model>
   <year>1984</year>
  </car>
 </dealership>
 <dealership name="Worst in Town Cars">
  <car>
   <make>Chevy</make>
   <model>Malibu</model>
   <year>1979</year>
  </car>
  <!-- This one should get filtered out, because it is the same as the
previous car in this dealers list-->
  <car>
   <make>Chevy</make>
   <model>Malibu</model>
   <year>1979</year>
  </car>
  <car>
   <make>Buick</make>
   <model>Skylark</model>
   <year>1984</year>
  </car>
 </dealership>
</carlist>

The stylesheet I am using is:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns="http://www.w3.org/TR/REC-html40";>
<xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes" />

<xsl:template match="/">

 <table border="1" cellpadding="3">
  <tr>
   <th>Dealer</th>
   <th>Make</th>
   <th>Model</th>
   <th>Year</th>
  </tr>

  <xsl:for-each select="carlist/dealership">
   <xsl:for-each select="./car">
    <xsl:choose>
     <xsl:when test="position() = 1">
      <tr>
       <td><xsl:value-of select="../@name"/></td>
       <td><xsl:value-of select="./make"/></td>
       <td><xsl:value-of select="./model"/></td>
       <td><xsl:value-of select="./year"/></td>
      </tr>
     </xsl:when>
     <xsl:when test="./make != ./preceding-sibling::car/make or ./model
!= ./preceding-sibling::car/model or ./year !=
./preceding-sibling::car/year">
      <tr>
       <td></td>
       <td><xsl:value-of select="./make"/></td>
       <td><xsl:value-of select="./model"/></td>
       <td><xsl:value-of select="./year"/></td>
      </tr>
     </xsl:when>
     <xsl:otherwise />
    </xsl:choose>
   </xsl:for-each>
  </xsl:for-each>

 </table>


</xsl:template>

</xsl:stylesheet>

This stylesheet results in a table that looks like this:

<table border="1" cellpadding="3"
xmlns="http://www.w3.org/TR/REC-html40";>
 <tr>
  <th>Dealer</th>
  <th>Make</th>
  <th>Model</th>
  <th>Year</th>
 </tr>
 <tr>
  <td>Fred's Used Cars</td>
  <td>Chevy</td>
  <td>Malibu</td>
  <td>1979</td>
 </tr>
 <tr>
  <td />
  <td>Dodge</td>
  <td>Charger</td>
  <td>1979</td>
 </tr>
 <tr>
  <td />
  <td>Chevy</td>
  <td>Malibu</td>
  <td>1979</td>
 </tr>
 <tr>
  <td>Best in Town Cars</td>
  <td>Chevy</td>
  <td>Malibu</td>
  <td>1979</td>
 </tr>
 <tr>
  <td />
  <td>Chevy</td>
  <td>Caprice</td>
  <td>1997</td>
 </tr>
 <tr>
  <td />
  <td>Buick</td>
  <td>Skylark</td>
  <td>1984</td>
 </tr>
 <tr>
  <td>Worst in Town Cars</td>
  <td>Chevy</td>
  <td>Malibu</td>
  <td>1979</td>
 </tr>
 <tr>
  <td />
  <td>Buick</td>
  <td>Skylark</td>
  <td>1984</td>
 </tr>
</table>

So it correctly filters out the second 1979 Chevy Malibu for the third
dealership, but not from the first dealership.

I recognize that the comparison:

<xsl:when test="./make != ./preceding-sibling::car/make or ./model !=
./preceding-sibling::car/model or ./year !=
./preceding-sibling::car/year">

is actually comparing this instance of ./make to only the first
preceding-sibling::car/make rather than what I would like,
which is all preceding-sibling::car/make values, but I can't figure out
how to make it compare with all of the preceding-sibling car/make
values.

Any help in penetrating my ignorance is greatly appreciated.

Regards,
Tim











 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>