Published:
5 January 2010
Concepts Discussed:
Data Source Filters, Field Types, Fields, and Pages

Step 5. Displaying Entries on a Page

This is the fun bit — building the user interface to allow your users to enter their postcode and see a list of stores near them.

Create a new Page (Blueprints > Pages) and title it Store Locator. Select the Stores By Location data source and click the Create Page button. Now you can view the debug view of the page and see the Stores By Location data source in action. Go to the following URL:

/store-locator/?debug

And you will see the <stores-by-location> XML produced by the data source.

Return to the list of pages and click on the link to store-locator.xsl — we are going to write some HTML and XSLT.

Start by removing the blank template in the middle of the XSLT, and replace it with this:

<xsl:template match="data"> 
    <html>
        <head>
            <title>Store Locator</title>
        </head>
        <body>

            <h1>Store Locator</h1>
            <xsl:call-template name="form"/>

            <xsl:choose>
                <xsl:when test="store-locator/entry">
                    <h2>Found <xsl:value-of select="count(store-locator/entry)"/> stores:</h2>
                    <ul>
                        <xsl:apply-templates select="store-locator/entry" mode="store"/>
                    </ul>
                </xsl:when>
                <xsl:otherwise>
                    <p>No stores found.</p>
                </xsl:otherwise>
            </xsl:choose>

        </body>
    </html> 
</xsl:template>

This template matches on the root <data> element in the page XML and contains the basic logic of our page. After the main heading a template is called that renders a search form. Next is a choose/when statement that first checks whether entries have been returned from the data source, then applies a template which will create a list item for each entry.

Under this template add another:

<xsl:template name="form">  
    <form>
        Find stores within <input type="text" name="range" value="{$url-range}"/>
        of your postcode <input type="text" name="postcode" value="{$url-postcode}"/>
        <input type="submit" value="Search"/>
    </form> 
</xsl:template>

This template is called from the first template. It writes a form into the HTML. Note the {$url-parameter} syntax on each input element — this will take the value from the querystring and re-populate the inputs on page load so the user doesn’t need to re-type again. However if you access the page without range=foo&postcode=bar on the URL Symphony won’t know to create parameters with these names and you will get an XSLT error.

Therefore you need to add these additional two lines. I usually add these at the very top (above the first xsl:template) since they are global to the stylesheet:

<xsl:param name="url-range" select="'2'"/>
<xsl:param name="url-postcode"/>

This creates the two names parameters, also providing a default for the “range” parameter.

Last but not least is a third template to render a list item for each store found:

<xsl:template match="entry" mode="store">
    <li>
        <xsl:value-of select="concat(name, ': ', address)"/>
    </li>
</xsl:template>

Your entire page XSLT should therefore 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"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
    omit-xml-declaration="yes"
    encoding="UTF-8"
    indent="yes" />

<xsl:param name="url-range" select="'2'"/>
<xsl:param name="url-postcode"/>

<xsl:template match="data"> 
    <html>
        <head>
            <title>Store Locator</title>
        </head>
        <body>

            <h1>Store Locator</h1>
            <xsl:call-template name="form"/>

            <xsl:choose>
                <xsl:when test="store-locator/entry">
                    <h2>Found <xsl:value-of select="count(store-locator/entry)"/> stores:</h2>
                    <ul>
                        <xsl:apply-templates select="store-locator/entry" mode="store"/>
                    </ul>
                </xsl:when>
                <xsl:otherwise>
                    <p>No stores found.</p>
                </xsl:otherwise>
            </xsl:choose>

        </body>
    </html> 
</xsl:template>

<xsl:template name="form">  
    <form>
        Find stores within <input type="text" name="range" value="{$url-range}"/>
        of your postcode <input type="text" name="postcode" value="{$url-postcode}"/>
        <input type="submit" value="Search"/>
    </form> 
</xsl:template>

<xsl:template match="entry" mode="store">
    <li>
        <xsl:value-of select="concat(name, ': ', address)"/>
    </li>
</xsl:template>

</xsl:stylesheet>

Now let’s see if this thing works…

Step 6. Testing and Tweaking →

Code Samples

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details