filtering products by category in exyus

2007-11-15 @ 03:54#

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>

code