filtering products by category in exyus
continuing with the recent project of shadowing scottgu's ASP.NET MVC demo, this entry shows how to use Exyus to support querystring filters on a data list. in this case, i want to add support for the ?category=[category-name] querystring parameter.
first, Exyus automatically parses the querystring arguments and makes them available as named arguments in XSLT. for example, the URL /xcs/data/products/?category=footwear produces the following named param object in XSLT: $category. this works with any number of arguments in the query string. also, any named elements in the resource class's UriPattern will be available. for example, this UriPattern: [UriPattern(@"/data/products/(?<pid>[^/]*)"] will result in the following XSLT named param: $pid. finally, other special items are available as XSLT named arguments such as $_method, $_path, and even $_user.
second, the list of resource items is produced using an XSLT document in the resource's documents folder named get_response_list.xsl. for the XmlFileHandler, the default XSLT file looks like this:
<?xml version='1.0' encoding='utf-8' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="no"/>
<xsl:template match="root">
<products xml:base="/xcs/data/products/">
<xsl:for-each select="item">
<product href="{.}" seq="{position()}">
<xsl:copy-of select="document(./@dref)/product/*"/>
</product>
</xsl:for-each>
</products>
</xsl:template>
</xsl:stylesheet>
however, since i want to add support for filtering the list based on the ?category querystring argument, i can modify the get_response_list.xsl to look like this:
<?xml version='1.0' encoding='utf-8' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="no"/>
<!-- named arguments -->
<xsl:param name="category" />
<!-- root -->
<xsl:template match="root">
<products xml:base="/xcs/data/products/" filter="{$category}">
<xsl:choose>
<xsl:when test="$category">
<xsl:apply-templates select="item" mode="category"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="item" />
</xsl:otherwise>
</xsl:choose>
</products>
</xsl:template>
<!-- unfiltered list -->
<xsl:template match="item">
<product href="{.}" seq="{position()}">
<xsl:copy-of select="document(./@dref)/product/*"/>
</product>
</xsl:template>
<!-- filtered by category -->
<xsl:template match="item" mode="category">
<xsl:if test="document(./@dref)/product/category=$category">
<product href="{.}" seq="{position()}">
<xsl:copy-of select="document(./@dref)/product/*"/>
</product>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
now, the resulting output can be filtered using the querystring argument. for example using /xcs/data/products/?category=outerwear returns the following:
<products xml:base="/xcs/data/products/" filter="outerwear"> <product href="coat" seq="1"> <id>999</id> <name>coat</name> <units-in-stock>10</units-in-stock> <category>outerwear</category> </product> </products>