Title
Description
Body <p>I ran into a <a href="http://overture21.com/forum/comments.php?DiscussionID=1814&page=1#Item_3">bug using Symphony</a>. I don't know enough about PHP and the Symphony core to be able to monkey around with it to discover what exactly is going on to produce the behaviour I am finding. I'm using Textile to format the entries for a client site I developed with Symphony 1.5. The site has since been updated to Symphony 1.7, but now when I resave data sources, the text formatter is disabled and the XML data for text area fields is being returned without formatting. Without child elements to parse, the XSL templates do not output the text when using instructions such as <code>xsl:copy-of select="body/*"</code>.</p> <h3>Considering the Options</h3> <p>So, how should I go about fixing the problem?</p> <ul> <li>Learn PHP, figure out how Symphony works, and fix the problem</li> <li>Use a manual hack every time I save a data source</li> <li>Rebuild from scratch</li> </ul> <p>Considering the options, I think I could probably rebuild the site faster than I could learn how to fix the bug. The hack doesn't seem like a good long term solution. If the source of the problem is a migration from an earlier version gone wrong, I might as well take this opportunity to rebuild the site and optimize the code, based on what I've learned since I first built the site. There are some things that I would do differently now.</p> <h3>Download Symphony</h3> <p><a href="http://21degrees.com.au/products/symphony/">Symphony</a> is a web publishing system developed by Twentyone Degrees in Brisbane, Australia. The system is powered by XML and XSLT, standards recommended by the W3C. Symphony 1.7 is free, but not open source. Symphony 2 Beta Revision 5 is the first open source release available from Twentyone Degrees. To download either version will require registering at <a href="http://accounts.symphony21.com/">Symphony Accounts</a>. Once you have logged in, click on the Download Symphony link to download Symphony 1.7.01.</p> <h3>Install Symphony</h3> <p>I will be developing the site on my local development server. I am using the Apache web server that comes installed on Mac OS X. I have added support for PHP 5 and MySQL 5. PHP is configured to process XSLT. Apache is configured to allow <code>.htaccess</code> files to override the default configuration settings and use <code>mod_rewrite</code> rules.</p> <h4>Create Virtual Hosts</h4> <p>I have created a couple virtual hosts by modifying my <code>/etc/hosts</code> file by adding the following:</p> <pre>127.0.0.1 sitename.dev 127.0.0.1 sitename.local</pre> <p>Then I modify the virtual hosts configuration file for Apache. For Mac OS X versions previous to 10.5 Leopard, I would add the code to the end of the Apache configuration file found here: <code>/etc/httpd/httpd.conf</code>. Now that Leopard is using Apache 2, the location for the virtual hosts configuration file is here: <code>/etc/apache2/extra/httpd-vhosts.conf</code>. I have my virtual hosts organized in my user Sites directory. I'll set the location of these virtual hosts with something like this:</p> <pre> <VirtualHost 127.0.0.1> ServerName sitename.dev DocumentRoot /Users/Stephen/Sites/domains/sitename/dev/www </VirtualHost> <VirtualHost 127.0.0.1> ServerName sitename.local DocumentRoot /Users/Stephen/Sites/domains/sitename/local/www </VirtualHost></pre> <p>Then, gracefully restart Apache, so the web server configuration can be updated:</p> <pre>sudo apachectl graceful</pre> <p>So, now I have two locations available for comparing the existing site and the development site. I have the existing site, in its backup state before things started to go awry, installed in the <code>sitename.local</code> location. The development site is in the <code>sitename.dev</code> location.</p> <p>I'm going to start without a workspace. This allows you to start with nothing but an empty database and an empty workspace. Otherwise, the default theme will be installed with example entries. I like to start clean.</p> <h4>Clean Install</h4> <p>For a clean install of Symphony, all you need are the following files/directories:</p> <ul> <li>index.php</li> <li>install.php</li> <li>symphony</li> </ul> <p>I have copied these files into the development directory, so the directory structure looks like this:</p> <pre>/Users/Stephen/Sites/domains/sitename/dev/www/index.php /Users/Stephen/Sites/domains/sitename/dev/www/install.php /Users/Stephen/Sites/domains/sitename/dev/www/symphony</pre> <h4>File Permissions</h4> <p>Before installing, the directory and file permissions need to be set to ensure that installation is trouble free. This can be accomplished by running the following commands in Terminal. First, change directories:</p> <pre>cd ~/Sites/domains/sitename/dev</pre> <p>Then, change the permissions to allow the installer to write files to these directories.</p> <pre>chmod -R 755 www chmod 777 www chmod 777 www/symphony</pre> <h4>Create a MySQL Database</h4> <p>Symphony requires a connection to a MySQL database, so I'll create this first before proceeding with the install. I use phpMyAdmin to create the database.</p> <pre>create database sitename_dev</pre> <h4>Installation</h4> <p>Navigate to the install file and follow the instructions to provide the database and user details:</p> <pre>http://sitename.dev/install.php</pre> <h5>Environment Settings</h5> <ul> <li>Root Path: /Users/Stephen/Sites/domains/sitename/dev/www</li> </ul> <h5>Database Connection</h5> <ul> <li>Database: sitename_dev</li> <li>Username: root</li> <li>Password: ****</li> <li>Host: localhost</li> <li>Port: 3306</li> <li>Table Prefix: sym_</li> </ul> <h5>Permission Settings</h5> <ul> <li>Files: 0777</li> <li>Directories: 0755</li> </ul> <h5>User Information</h5> <ul> <li>Username</li> <li>Password</li> </ul> <h5>Personal Information</h5> <ul> <li>First Name</li> <li>Last Name</li> <li>Email Address</li> </ul> <p>The install takes a single click, and I am now looking at the Symphony login window, as all has gone well. This is where I will be logging into the Symphony administration interface.</p> <pre>http://sitename.dev/symphony</pre> <p>I like to be able modify XSL templates and configuration files directly from the file system, using TextWrangler or Coda as my editors of choice. If I list the files in Terminal to determine the permissions, I see that the files have been created as the default Apache user, <code>_www</code>. <pre> cd ~/Sites/domains/sitename/dev/www ls -la drwxr-xr-x 12 Stephen Stephen 408 Jul 19 14:45 . drwxr-xr-x 4 Stephen Stephen 136 Jul 19 07:20 .. -rwxr-xr-x@ 1 Stephen Stephen 6148 Jul 19 14:22 .DS_Store -rwxrwxrwx 1 _www Stephen 1883 Jul 19 12:50 .htaccess -rwxr-xr-x@ 1 Stephen Stephen 1050 Apr 1 2007 README drwxr-xr-x 2 _www Stephen 68 Jul 19 12:50 campfire -rwxr-xr-x@ 1 Stephen Stephen 6460 Mar 16 2007 index.php -rw-r--r-- 1 _www Stephen 2053 Jul 19 12:50 install-log.txt -rw-r--r--@ 1 Stephen Stephen 88956 Mar 27 2007 install.php drwxr-xr-x 6 _www Stephen 204 Jul 19 12:50 manifest drwxr-xr-x@ 12 Stephen Stephen 408 Mar 22 2007 symphony drwxr-xr-x 9 _www Stephen 306 Jul 19 12:50 workspace </pre> <p>This list clearly shows the files and directories that Symphony has created during the install process. To make sure I can still access these files from the file system without much fuss, I'm going to change the permissions on these files, recursively changing the owner and group to my username:</p> <pre>cd ~/Sites/domains/sitename/dev sudo chown -R Stephen:Stephen www</pre> <p>The first thing I would want to do at this point is to delete the install.php file for security reasons, especially if I was working on a production server.</p> <h3>Hello World</h3> <p>Symphony is installed, so I'll start going through the process of building the home page. For anyone unfamiliar with Symphony, I have created an introduction to Building a Symphony Theme. Unfortunately, I haven't had a chance to finish the tutorial. I hope I can remedy this by completing the documentation for developing this site, assuming that everyone knows the basics as detailed in these articles:</p> <ul> <li><a href="http://bauhouse.ca/journal/building-a-symphony-theme-part-1/">Building a Symphony Theme: Part 1</a></li> <li><a href="http://bauhouse.ca/journal/building-a-symphony-theme-part-2/">Building a Symphony Theme: Part 2</a></li> <li><a href="http://bauhouse.ca/journal/building-a-symphony-theme-part-3/">Building a Symphony Theme: Part 3</a></li> <li><a href="http://bauhouse.ca/journal/building-a-symphony-theme-part-4/">Building a Symphony Theme: Part 4</a></li> <li><a href="http://bauhouse.ca/journal/building-a-symphony-theme-part-5/">Building a Symphony Theme: Part 5</a></li> </ul> <h3>Install Campfire Services</h3> <p>This is an important step, since the preference set for each Author determines the text formatter to be used for all entries created by that Author. Text formatters are generally added to Symphony as Campfire Services. I will be using the Textile text formatter. Check out the available <a href="http://overture21.com/campfire-service/">Campfire Services on the Overture Forum</a>.</p> <h3>Plan the Site Structure</h3> <p>The site requires several types of content: static content pages, news and archives, images, projects organized by country and project partner, a repository of resources, a means of registering members who are provided with access to resources by logging into a members area. Future requirements include photo and video galleries. With that in mind, the site will be built with the following sections:</p> <h4>Sections</h4> <ul> <li>Content</li> <li>News</li> <li>Resources</li> <li>Categories</li> <li>Campaigns</li> <li>Projects</li> <li>Countries</li> <li>Partners</li> <li>Members</li> </ul> <p>With a site structure in mind, I can develop a custom administration interface by populating each section with custom fields to manage all the types of data that will be used by each section. I have a choice of several different field types: Text Input, Text Area, Select Box, Check Box, File Attachment and Section Link (<a href="http://overture21.com/forum/comments.php?DiscussionID=453">one of my contributions to the development of Symphony</a>).</p> <h4>Custom Fields</h4> <ul> <li>Content <ul> <li>Title (Text Input)</li> <li>Page (Select Box)</li> <li>Body (Text Area)</li> <li>Photo (File Attachment)</li> <li>Photo Title (Text Input)</li> <li>Publish (Check Box)</li> </ul> </li> <li>News <ul> <li>Title (Text Input)</li> <li>Category (Section Link: Categories)</li> <li>Description (Text Area)</li> <li>Body (Text Area)</li> <li>Photo (File Attachment)</li> <li>Photo Title (Text Input)</li> <li>Publish (Check Box)</li> </ul> </li> <li>Resources <ul> <li>Resource (Text Input)</li> <li>File (File Attachment)</li> <li>Category (Section Link: Categories)</li> <li>Description (Text Area)</li> </ul> </li> <li>Categories <ul> <li>Title (Text Input)</li> <li>Description (Text Area)</li> </ul> </li> <li>Campaigns <ul> <li>Campaign Year (Text Input)</li> <li>Description (Text Area)</li> <li>Partners (Section Link: Multiple)</li> <li>Countries (Section Link: Multiple)</li> </ul> </li> <li>Projects <ul> <li>Project (Text Input)</li> <li>Project Year (Select Box)</li> <li>Project Country (Section Link: Countries)</li> <li>Project Partner (Section Link: Partners)</li> <li>Description (Text Area)</li> <li>Details (Text Area)</li> <li>Photo (File Attachment)</li> <li>Photo Title [Portrait Orientation] (Checkbox)</li> <li>Sort (Text Input)</li> </ul> </li> <li>Countries <ul> <li>Country (Text Input)</li> <li>Continent (Select Box)</li> <li>Country Code (Text Input)</li> <li>Description (Text Area)</li> <li>Government (Text Input)</li> </ul> </li> <li>Partners <ul> <li>Partner (Text Input)</li> <li>Full Name (Text Input)</li> <li>Type (Select Box)</li> <li>Description (Text Area)</li> <li>Website Title (Text Input)</li> <li>Website URL (Text Input)</li> <li>Logo (File Attachment)</li> </ul> </li> <li>Members <ul> <li>Username (Text Input)</li> <li>First Name (Text Input)</li> <li>Last Name (Text Input)</li> <li>Email (Text Input)</li> <li>Phone (Text Input)</li> <li>Address 1 (Text Input)</li> <li>Address 2 (Text Input)</li> <li>City (Text Input)</li> <li>Province / State (Text Input)</li> <li>Country (Text Input)</li> <li>Postal / Zip Code (Text Input)</li> <li>Role (Select Box)</li> <li>Role Other (Text Input)</li> <li>Communication Method (Select Box)</li> <li>Organizing Class (Text Input)</li> <li>Organization Name (Text Input)</li> <li>Organization Type (Select Box)</li> <li>Organization Type Other (Text Input)</li> <li>Organization Address 1 (Text Input)</li> <li>Organization Address 2 (Text Input)</li> <li>Organization City (Text Input)</li> <li>Organization Province / State (Text Input)</li> <li>Organization Country (Text Input)</li> <li>Organization Postal / Zip Code (Text Input)</li> <li>Organization Email (Text Input)</li> <li>Organization Phone (Text Input)</li> <li>Organization Facsimile (Text Input)</li> </ul> </li> </ul> <h3>Create the Master Template</h3> <p>Create a new master template [Blueprints : Components : Create New] called "default".</p> <p>Then create a page [Blueprints : Pages : Create New] called "Home", configuring the page type as "index", that uses the <code>default.xsl</code> master template.</p> <p>The default template will look something like this:</p> <pre> <?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" encoding="UTF-8" indent="yes" /> <xsl:param name="campaign-year" select="2008"/> <xsl:param name="logged-in" select="/data/events/user/@logged-in"/> <xsl:template match="/"> <html> <head> <title><xsl:value-of select="$website-name"/> - <xsl:value-of select="$page-title"/></title> <link rel="stylesheet" type="text/css" media="screen" href="{$root}/workspace/assets/css/hri.css"/> <link rel="alternate" type="application/rss+xml" href="/rss/" /> </head> <body id="section-{$current-page}"> <div id="wrapper"> <ul id="global-nav"> <xsl:call-template name="global-nav"/> </ul> <div id="header"> <h1><a href="{$root}" id="hri-link"><span><xsl:value-of select="$website-name"/></span></a></h1> <div id="main-nav"> <ul> <xsl:call-template name="navigation"/> </ul> </div> </div> <div id="body-container"> <xsl:apply-templates /> <div class="clear"></div> </div> <div id="footer"> <div id="copyright"> <p>Copyright 2008 Hunger Response International. All rights reserved. <a href="{$root}/privacy/" title="Hunger Response International / Rice Raiser Privacy Policy">Privacy Policy</a> | Site Design by <a href="http://www.bauhouse.ca/" title="Bauhouse Visual Communications">Bauhouse</a></p> </div> </div> </div> </body> </html> </xsl:template> </xsl:stylesheet> </pre> <h3>Create the Navigation Utility</h3> <p>This template makes reference to a couple templates that do not yet exist. I can add these named templates after the match template. Or if I want this template to be accessible to all master templates, I can create a utility without attaching it to a specific data source.</p> <pre> <xsl:template name="global-nav"> <xsl:for-each select="/data/navigation/page[@type = 'global' or @type = 'index']"> <xsl:choose> <xsl:when test="@type = 'index'"> <li> <xsl:if test="@handle = $current-page"> <xsl:attribute name="class">current</xsl:attribute> </xsl:if> <a href="{$root}/"><xsl:value-of select="title"/></a> </li> </xsl:when> <xsl:otherwise> <li> <xsl:if test="@handle = $current-page"> <xsl:attribute name="class">current</xsl:attribute> </xsl:if> <a href="{$root}/{@handle}/"><xsl:value-of select="title"/></a> </li> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <xsl:template name="main-nav"> <xsl:choose> <xsl:when test="$logged-in='true'"> <xsl:for-each select="/data/navigation/page[@type='members']"> <li> <xsl:if test="@handle = $current-page"> <xsl:attribute name="class">current</xsl:attribute> </xsl:if> <a href="{$root}/{@handle}/"><xsl:value-of select="title"/></a> </li> </xsl:for-each> <li><a>Logged in as <xsl:value-of select="/data/events/user/username"/></a></li> <li><a href="{$root}/symphony/?page=/logout/">Logout</a></li> </xsl:when> <xsl:otherwise> <xsl:for-each select="/data/navigation/page[@type='default' or @type='login']"> <li> <xsl:if test="@handle = $current-page"> <xsl:attribute name="class">current</xsl:attribute> </xsl:if> <a href="{$root}/{@handle}/"><xsl:value-of select="title"/></a> </li> </xsl:for-each> </xsl:otherwise> </xsl:choose> </xsl:template> </pre> <h3>Create the Page Structure</h3> <p>With the navigation in place, now we can start building the page structure. The pages have been created with the following parameters: Title (Master, URL Schema, Page Type)</p> <ul> <li>Home (default.xsl, entry, index)</li> <li>Partners (index.xsl, entry, global)</li> <li>Projects (index.xsl, year/entry, global)</li> <li>News (default.xsl, year/month/day/entry, global)</li> <li>Donate (default.xsl, entry, global)</li> <li>About (default.xsl, entry, global) <ul> <li>Board of Directors (default.xsl, entry, about) <li>Advisory Council (default.xsl, entry, about) </ul> </li> <li>Contact (default.xsl, entry, global) <li>Resources (default.xsl, category/entry, members) <li>Register (default.xsl, n/a, Default) <li>Login (default.xsl, entry, login) <li>Privacy (default.xsl, entry, legal) <li>Maintenance (default.xsl, n/a, Maintenance) <li>Page Not Found (default.xsl, n/a, Page Not Found) </ul> <h3>Creating Templates for Common Elements</h3> <p>I'm going to make sure that modifying the templates will be necessary only in a single place. I'll create a template for common elements such as the head element, navigation and footer. The default master template now looks like this:</p> <pre> <?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" encoding="UTF-8" indent="yes" /> <xsl:param name="campaign-year" select="2008"/> <xsl:param name="logged-in" select="/data/events/user/@logged-in"/> <xsl:template match="/"> <html> <xsl:call-template name="head"/> <body id="section-{$current-page}"> <div id="wrapper"> <xsl:call-template name="navigation"/> <div id="body-container"> <xsl:apply-templates /> <div class="clear"></div> </div> <xsl:call-template name="footer"/> </div> </body> </html> </xsl:template> </xsl:stylesheet> </pre> <p>The common elements are being called from a utility called "Common" that contains three named templates:</p> <pre> <xsl:template name="head"> <head> <title><xsl:value-of select="$website-name"/> - <xsl:value-of select="$page-title"/></title> <link rel="stylesheet" type="text/css" media="screen" href="{$root}/workspace/assets/css/hri.css"/> <link rel="alternate" type="application/rss+xml" href="/rss/" /> </head> </xsl:template> <xsl:template name="navigation"> <ul id="global-nav"> <xsl:call-template name="global-nav"/> </ul> <div id="header"> <h1><a href="{$root}" id="hri-link"><span><xsl:value-of select="$website-name"/></span></a></h1> <div id="main-nav"> <ul> <xsl:call-template name="main-nav"/> </ul> </div> </div> </xsl:template> <xsl:template name="footer"> <div id="footer"> <div id="copyright"> <p>Copyright 2008 Hunger Response International. All rights reserved. <a href="{$root}/privacy/" title="Hunger Response International / Rice Raiser Privacy Policy">Privacy Policy</a> | Site Design by <a href="http://www.bauhouse.ca/" title="Bauhouse Visual Communications">Bauhouse</a></p> </div> </div> </xsl:template> </pre> <h3>Content and Navigation Utilities</h3> <p>I've created some templates to help automate the process of building content and section menus for pages. For page content, I have created a "Page Content" utility.</p> <h4>Page Content</h4> <pre> <xsl:template name="page-body"> <xsl:param name="page-datasource" select="content/entry"/> <div id="section"> <div class="section-head"> <h2> <a href="{$root}/{$current-page}/"> <xsl:value-of select="$page-title"/> </a> </h2> </div> <div class="section-menu"> <ul> <xsl:call-template name="section-menu"> <xsl:with-param name="page-datasource" select="$page-datasource"/> </xsl:call-template> </ul> </div> </div> <div id="main-content"> <xsl:call-template name="page-content"> <xsl:with-param name="page-datasource" select="$page-datasource" /> </xsl:call-template> </div> </xsl:template> <xsl:template name="page-content"> <xsl:param name="page-datasource" select="content/entry"/> <xsl:choose> <xsl:when test="($entry)"> <xsl:for-each select="$page-datasource[@handle=$entry]"> <div class="content-head"> <h2><a href="{$root}/{$current-page}/{@handle}/" title="Permanent link to this article"><xsl:value-of select="fields/title"/></a></h2> </div> <div class="content-body"> <xsl:if test="(fields/photo/item)"> <p class="photo"><img src="{$root}/{fields/photo/item/path}" title="{fields/photo-title}"/></p> </xsl:if> <xsl:apply-templates select="fields/body/*" mode="root-url"/> </div> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:for-each select="$page-datasource[fields/page/@handle=$current-page][1]"> <div class="content-head"> <h2><a href="{$root}/{$current-page}/{@handle}/" title="Permanent link to this article"><xsl:value-of select="fields/title"/></a></h2> </div> <div class="content-body"> <xsl:apply-templates select="fields/body/*" mode="root-url"/> </div> </xsl:for-each> </xsl:otherwise> </xsl:choose> </xsl:template> </pre> <h4>Page Navigation</h4> <p>The "Page Content" utility calls templates from the "Page Navigation" utility:</p> <pre> <xsl:template name="section-menu"> <xsl:param name="page-datasource" select="/data/content-titles/entry"/> <xsl:param name="for-section" select="$current-page"/> <xsl:for-each select="$page-datasource[fields/page/@handle=$for-section]"> <li> <xsl:if test="(not($entry) and position() = 1 and $current-page = $for-section) or @handle = $entry"> <xsl:attribute name="class">current</xsl:attribute> </xsl:if> <a href="{$root}/{$for-section}/{@handle}/"><xsl:value-of select="fields/title"/></a> </li> </xsl:for-each> </xsl:template> <xsl:template name="projects-menu"> <xsl:param name="page-datasource" select="/data/projects/entry"/> <xsl:param name="for-year" select="2007"/> <xsl:for-each select="$page-datasource[fields/project-year=$for-year]"> <xsl:sort select="fields/project-number"/> <li> <xsl:if test="($year and not($entry) and position() = 1) or @handle = $entry"> <xsl:attribute name="class">current</xsl:attribute> </xsl:if> <a href="{$root}/projects/{$for-year}/{@handle}/"><xsl:value-of select="fields/project"/></a> </li> </xsl:for-each> </xsl:template> <xsl:template name="partners-menu"> <xsl:param name="global" select="'no'"/> <xsl:for-each select="partners/entry[fields/global=$global]"> <li> <xsl:if test="@handle = $entry"> <xsl:attribute name="class">current</xsl:attribute> </xsl:if> <a href="{$root}/partners/{@handle}/"><xsl:value-of select="fields/full-name"/></a> </li> </xsl:for-each> </xsl:template> </pre> <h3>Root URL Utility</h3> <p>The <code>xsl:apply-templates</code> instruction used by the <code>page-content</code> template is referring a set of templates that I use to define a mode called <code>root-url</code>. This allows me to publish the Symphony site within a subdirectory while automatically modifying absolute href attributes that have been created as entry content to point to the href relative to the current location using Symphony's <code>$root</code> parameter.</p> <pre> <xsl:template match="*" mode="root-url"> <xsl:element name="{name(.)}"> <xsl:apply-templates select="@*" mode="root-url"/> <xsl:apply-templates mode="root-url"/> </xsl:element> </xsl:template> <xsl:template match="@*" mode="root-url"> <xsl:attribute name="{name(.)}"><xsl:value-of select="."/></xsl:attribute> </xsl:template> <xsl:template match="text()" mode="root-url"> <xsl:value-of select="."/> </xsl:template> <xsl:template match="img[substring(@src,1,1)='/']" mode="root-url"> <img> <xsl:apply-templates select="@*" mode="root-url"/> <xsl:attribute name="src"><xsl:value-of select="$root"/><xsl:value-of select="@src"/></xsl:attribute> </img> </xsl:template> <xsl:template match="a[substring(@href,1,1)='/']" mode="root-url"> <a> <xsl:apply-templates select="@*" mode="root-url"/> <xsl:attribute name="href"><xsl:value-of select="$root"/><xsl:value-of select="@href"/></xsl:attribute> <xsl:value-of select="."/> <xsl:apply-templates select="./*" mode="root-url"/> </a> </xsl:template> </pre> <h3>Utilities</h3> <p>So far, I have the following list of utilities that are used by all pages, since they have not been attached to a specific data source:</p> <ul> <li>Common (common.xsl)</li> <li>Navigation (navigation.xsl)</li> <li>Page Content (page-content.xsl)</li> <li>Page Navigation (page-navigation.xsl)</li> <li>Root URL (root-url.xsl)</li> </ul>
Section Tutorials Contact Journal About Home
Category Applications Design History Ideas Technology
Tags
Date
DesignProjectX | The digital sandbox of Stephen Bau