Re: [xsl] Determining uniqueness based on mulitple element values

Subject: Re: [xsl] Determining uniqueness based on mulitple element values
From: Tim Lewis <lewist@xxxxxxxxxxx>
Date: Mon, 16 Dec 2002 08:42:18 -0500
Joerg,

This is the second time you've saved me.

Thanks,
Tim

Joerg Heinicke wrote:

> Hello Tim,
>
> the error is in your for-each loop. You use the != operator instead of
> not().
>
> preceding-sibling::car/make != 'Dodge' is true, if there exists *one*
> <car>, which *is not* a Dodge.
>
> not(preceding-sibling::car/make = 'Dodge') is true if there exists *no*
> car, which *is* a Dodge.
>
> Furthermore there is the problem that the comparisons for make, model
> and year can be done to different cars. In the following example car 3
> will be filtered out, because a car exists with the same make and model
> and another one with the same year:
>
>    <car>
>     <make>Chevy</make>
>     <model>Malibu</model>
>     <year>1985</year>
>    </car>
>    <car>
>     <make>Dodge</make>
>     <model>Charger</model>
>     <year>1979</year>
>    </car>
>    <car>
>     <make>Chevy</make>
>     <model>Malibu</model>
>     <year>1979</year>
>    </car>
>
> Your code corrected and optimized can look like:
>
> <xsl:for-each select="carlist/dealership">
>    <xsl:for-each select="car">
>      <xsl:if test="not(preceding-sibling::car[make = current()/make and
> model = current()/model and year = current()/year])">
>        <tr>
>          <td>
>            <xsl:if test="position() = 1">
>              <xsl:value-of select="../@name"/>
>            </xsl:if>
>          </td>
>          <td><xsl:value-of select="make"/></td>
>          <td><xsl:value-of select="model"/></td>
>          <td><xsl:value-of select="year"/></td>
>        </tr>
>      </xsl:if>
>    </xsl:for-each>
> </xsl:for-each>
>
> I prefer the grouping via keys:
>
> <xsl:key name="cars" match="car" use="concat(../@name, make, model, year)"/>
>
> and later in the template:
>
> <xsl:for-each select="carlist/dealership">
>    <xsl:for-each select="car[generate-id() = generate-id(key('cars',
>                             concat(../@name, make, model, year)))]">
>        <tr>
>          <td>
>            <xsl:if test="position() = 1">
>              <xsl:value-of select="../@name"/>
>            </xsl:if>
>          </td>
>          <td><xsl:value-of select="make"/></td>
>          <td><xsl:value-of select="model"/></td>
>          <td><xsl:value-of select="year"/></td>
>        </tr>
>    </xsl:for-each>
> </xsl:for-each>
>
> This is mostly simpler and faster.
>
> Regards,
>
> Joerg
>
> >   <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>
>
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


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


Current Thread