[xsl] Dynamic Filter Menus

Subject: [xsl] Dynamic Filter Menus
From: brian.witgen@xxxxxxxxxxx
Date: Fri, 26 Oct 2001 08:41:51 -0500
I am trying to take a list of entries like such:

<entry date="Fri Wed Sep 26 06:57:55 CDT 2001"
     vendor="newmanufacturer"
     category="gorycat2"
     version="2.9"
     title="First line of info."
     description="Last line you'll see.">
</entry>
<entry date="Mon Wed Sep 26 06:57:55 CDT 2001"
     vendor="testingamaker"
     category="printers"
     version="3.4"
     title="print me a file."
     description="now go get it.">
</entry>
<entry date="Fri Wed Sep 26 06:57:55 CDT 2001"
     vendor="newmanufacturer"
     category="gorycat3"
     version="2.9"
     title="Second of info."
     description="First line you'll see.">
</entry>

....and with those entries, I have created 3 keys based on the vendor, category, and version:

<xsl:key name="venkey" match="entry" use="@vendor" />
<xsl:key name="catkey" match="entry" use="@category" />
<xsl:key name="verkey" match="entry" use="@version" />

The menus are a unique list of the vendors, categories, or versions to
select. I dont have any probelm with getting the initial unique list when
no filters have been selected yet. I am trying to make the menus work in
such a way that when one filter is selected, the other two menus that do
not have a filter selected will show a unique list of only those values
that match the selected filter.

Example:  With the entries above, if I choose version 2.9 as a filter, then
only "newmanufacturer" will show up in the vendor menu (once being unique)
and "gorycat2" and "gorycat3" will both show up in the category menu.

I have an xml file that is updated with the selected filter for each menu
through javascript and pulled into the template as parameters:

               <xsl:call-template name="filtermenus">
                    <xsl:with-param name="pven" select="/docs/vendorfilter" />
                    <xsl:with-param name="pcat" select="/docs/categoryfilter" />
                    <xsl:with-param name="pver" select="/docs/versionfilter" />
               </xsl:call-template>

Here is a snippet of what I am using now for one of the menus:

   <xsl:variable name="uven" select="entry[generate-id() = generate-id(key('venkey', @vendor)[1])]"/>
   <xsl:variable name="ucat" select="entry[generate-id() = generate-id(key('catkey', @category)[1])]"/>
   <xsl:variable name="uver" select="entry[generate-id() = generate-id(key('verkey', @version)[1])]"/>

                    <select name="filterbyvendor" style="width: 90pt">
                       <xsl:if test="$pven!='No-Filter'">
                           <option>No-Filter</option>
                           <option selected="selected"><xsl:value-of select="$pven" /></option>
                       </xsl:if>
                       <xsl:if test="$pven='No-Filter'">
                           <option selected="selected">No-Filter</option>
                           <xsl:choose>
                               <xsl:when test="$pcat!='No-Filter' and $pver='No-Filter'">
                                   <xsl:for-each select="$uven">
                                       <xsl:sort select="@vendor" />
                                       <xsl:for-each select="key('venkey', @vendor)">
                                           <xsl:variable name="test" select="boolean(key('venkey', @vendor) and @category=$pcat)" />
                                           <xsl:if test="$test='true'">
                                               <option><xsl:value-of select="@vendor"/></option>
                                           </xsl:if>
                                       </xsl:for-each>
                                   </xsl:for-each>
                               </xsl:when>
                               <xsl:when test="$pcat='No-Filter' and $pver!='No-Filter'">
                                   <xsl:for-each select="$uven">
                                       <xsl:sort select="@vendor" />
                                       <xsl:for-each select="key('venkey', @vendor)">
                                           <xsl:variable name="test" select="boolean(key('venkey', @vendor) and @version=$pver)" />
                                           <xsl:if test="$test='true'">
                                               <option><xsl:value-of select="@vendor"/></option>
                                           </xsl:if>
                                       </xsl:for-each>
                                   </xsl:for-each>
                               </xsl:when>
                               <xsl:when test="$pcat!='No-Filter' and $pver!='No-Filter'">
                                   <xsl:for-each select="$uven">
                                       <xsl:sort select="@vendor" />
                                       <xsl:for-each select="key('venkey', @vendor)">
                                       <xsl:variable name="test" select="boolean(key('venkey', @vendor) and @category=$pcat and @version=$pver)" />
                                           <xsl:if test="$test='true'">
                                               <option><xsl:value-of select="@vendor"/></option>
                                           </xsl:if>
                                       </xsl:for-each>
                                   </xsl:for-each>
                               </xsl:when>
                               <xsl:otherwise>
                                   <xsl:for-each select="$uven">
                                       <xsl:sort select="@vendor" />
                                       <option><xsl:value-of select="
@vendor"/></option>
                                   </xsl:for-each>
                               </xsl:otherwise>
                           </xsl:choose>
                        </xsl:if>
                    </select>
                 </td>
                 <td align="center">

The problem arises from the two xsl:foreach statements in each xsl:when. If
I only use the outer xsl:foreach which selects the list of unique vendors,
then the boolean test will only put a vendor in the menu if it is true for
the first vendor in each group (which is how we got the unique value in the
first place). When I put the second xsl:foreach statement in which selects
every entry in the vendor group that the outer xsl:foreach is on at that
point in the loop, then it won't give me a unique menu list. I have tried
using "count" in different ways, using variables, parameters, etc, and I
always end up back in the same situation. Does anyone have any idea how to
fix one loop or the other?


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


Current Thread