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>