[ Index ]

PHP Cross Reference of Web Application Component Toolkit

title

Body

[close]

/examples/tutorials/rss/ -> tutorial.rss.html (source)

   1  <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
   2        'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
   3  <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
   4    <head>
   5      <meta http-equiv='Content-Type'
   6        content='text/html; charset=iso-8859-1' />
   7  
   8      <title>Generating an RSS feed with WACT</title>
   9  
  10      <link href="../tutorial.css" type="text/css" rel="stylesheet"/>
  11  
  12    </head>
  13    <body>
  14  
  15      <h1>Generating syndication feeds with WACT</h1>
  16  
  17      <p><a href="../" shape="rect">Tutorials Home</a></p>
  18  
  19      <p class="abstract">This tutorial demonstrates that
  20  
  21      <acronym title="The Web Application Component Toolkit">WACT</acronym>
  22  
  23      can be used to generate content other than HTML. It assumes no prior
  24      knowledge of the WACT framework.</p>
  25  
  26      <p class="docinfo">
  27          Author: <a href="mailto:jon@bangoid.com" shape="rect">Jon Ramsey</a><br />
  28          Created: 2003-12-07<br />
  29          $Date: 2004/11/12 21:25:03 $<br />
  30          $Author: jeffmoore $<br />
  31          $Revision: 1.6 $<br />
  32      </p>
  33      <h2>Syndicate Me</h2>
  34  
  35      <p>So, you have a lot to say, and you think that the world should hear
  36      it. Are you sure? Oh, ok, well then you <strong>need a feed</strong>. This
  37      tutorial walks you through creating a simple syndication feed using WACT
  38      templating. The rest is up to you.</p>
  39  
  40      <h2>Choices, choices, an awful lot of choices</h2>
  41  
  42      <p>Syndication formats come in a <a
  43      href="http://xml.com/pub/a/2002/12/18/dive-into-xml.html"
  44      shape="rect">multitude of flavors</a>. With all the <a
  45      href="http://www.sifry.com/alerts/archives/000299.html"
  46      shape="rect">controversy</a> flying around it can be hard to choose which
  47      format you should use for your application. I'm going to plump for <a
  48      href="http://web.resource.org/rss/1.0/" shape="rect">RSS 1.0</a>.</p>
  49  
  50      <h3>What makes a good feed?</h3>
  51  
  52      <p>Burgers.</p>
  53  
  54      <p>Oh, a syndication feed&hellip; well, a feed is a simple beast providing
  55      at least two things to its users:</p>
  56  
  57      <ul>
  58        <li>Some general information about the source (e.g. publication date,
  59        copyright info.)</li>
  60  
  61        <li>A collection of (<em>more or less</em>) interesting items</li>
  62      </ul>
  63  
  64      <p>Through the use of some of basic <a
  65      href="http://wact.sourceforge.net/index.php/SupportedTags" shape="rect">WACT
  66      tags</a> we can create and populate feed templates in a very simple
  67      fashion.</p>
  68  
  69      <h2>Infrastructure</h2>
  70  
  71      <p>I'm going to be using a <a
  72      href="http://wact.sourceforge.net/index.php/PageController"
  73      shape="rect">Page Controller</a>, a <a
  74      href="http://wact.sourceforge.net/index.php/Template"
  75      shape="rect">Template</a> and a config file to generate the output feed.</p>
  76  
  77      <h3>Control freak</h3>
  78  
  79      <p>First off, lets get the controller moving. We'll also use this
  80        opportunity to get <strong>&ldquo;Hello World!&rdquo;</strong> out of the
  81        way. <code>feed.1.php</code>:</p>
  82  
  83      <pre xml:space="preserve">
  84  &lt;?php
  85  require_once '../wact/framework/common.inc.php'; /* Your path to WACT may differ... */
  86  require_once WACT_ROOT . 'template/template.inc.php'; /* Include the base WACT template system */
  87  
  88  $feed =& new Template('/hello-world.1.html'); /* generate a template object from a template file */
  89  $feed->display();               /* display the rendered template */
  90  ?&gt;</pre>
  91  
  92      <p>Things to note:</p>
  93  
  94      <ul>
  95        <li>The first require (for WACT common functions) must be given an
  96        absolute path to your WACT installation. The second require can use the
  97        <code>WACT_ROOT</code> constant &mdash; it points to the framework
  98        directory under your WACT installation.</li>
  99  
 100        <li>The second require (<code>template.inc.php</code>) brings in the WACT
 101        templating system.</li>
 102  
 103        <li>We set up a <code>Template</code> object using the file
 104        <code>/hello-world.1.html</code>.</li>
 105  
 106        <li>We then call the Template object's <code>display()</code> method. This
 107        will output the compiled template to a visiting user agent.</li>
 108      </ul>
 109  
 110      <p>Hitting <code>feed.1.php</code> from a browser
 111        at this point will generate an error indicating that
 112        <code>hello-world.1.html</code> can't be found. I guess we'd better create
 113        it.</p>
 114  
 115      <h3>Absolute beginners</h3>
 116  
 117      <p>You probably noticed that the path to the template file is absolute. But
 118        absolute in relation to what?</p>
 119  
 120      <p>The default WACT templating <a
 121        href="http://wact.sourceforge.net/index.php/FileScheme" shape="rect">file
 122        scheme</a> expects to find template files in a directory
 123        <code>./template/source</code>. When WACT compiles templates it expects to
 124        be able to write them to a directory <code>./templates/compiled</code>
 125        &mdash; this directory needs to be writable by your webserver. Let's set
 126        these directories up:</p>
 127  
 128      <pre xml:space="preserve">
 129  $ mkdir templates
 130  $ mkdir templates/source
 131  $ mkdir templates/compiled
 132  $ chmod 777 templates/compiled</pre>
 133  
 134      <h3>Canonical, dull</h3>
 135  
 136      <p>Ok, with that out of the way we can finally create our very exciting
 137        template, saving it as
 138        <code>templates/source/hello-world.1.html</code>:</p>
 139  
 140      <pre xml:space="preserve">
 141  &lt;html&gt;
 142  &lt;body&gt;
 143  &lt;h1&gt;Hello, World!&lt;/h1&gt;
 144  &lt;/body&gt;
 145  &lt;/html&gt;</pre>
 146  
 147      <p>You'll notice that it's just a vanilla HTML file (missing a DOCTYPE
 148      etc. but hey).</p>
 149  
 150      <p>Now hit <a href="feed.1.php" shape="rect">feed.1.php</a> from your
 151      browser, pat yourself on the back, go home and sleep the contented sleep of
 152      someone who has implemented <strong>&ldquo;Hello, World!&rdquo;</strong> in
 153      a new framework. Really, what more do you people want?</p>
 154  
 155      <h2>Fame</h2>
 156  
 157      <p>Ok, just to make you happy. Your 15 minutes are coming right
 158      up. <code>feed.2.php</code>:</p>
 159  
 160      <pre xml:space="preserve">
 161  &lt;?php
 162  require_once '../wact/framework/common.inc.php'; /* Your path to WACT may differ... */
 163  require_once WACT_ROOT . 'template/template.inc.php'; /* Include the base WACT template system */
 164  
 165  $feed =& new Template('/hello-world.2.html'); /* generate a template object from a template file */
 166  $feed->set('name', 'Your name here');
 167  $feed->display();               /* display the rendered template */
 168  ?&gt;</pre>
 169  
 170      <p>Things to note:</p>
 171  
 172      <ul>
 173        <li>The template source has changed to <code>/hello-world.2.html</code></li>
 174  
 175        <li>We are calling the <code>set()</code> method of the
 176        <code>Template</code> object, with the arguments <code>'name'</code> and
 177        <code>'Your name here'</code>. The <code>set()</code> method is part of
 178        WACT's <a href="http://wact.sourceforge.net/index.php/DataSpace"
 179        shape="rect">DataSpace interface</a>.</li>
 180      </ul>
 181  
 182      <p>We also create the new template file
 183      <code>templates/source/hello-world.2.html</code>:</p>
 184  
 185      <pre xml:space="preserve">
 186  &lt;html&gt;
 187  &lt;body&gt;
 188  &lt;h1&gt;Hello, World!&lt;/h1&gt;
 189  &lt;h2&gt;From &amp;ldquo;{$name}&amp;rdquo;.&lt;/h2&gt;
 190  &lt;/body&gt;
 191  &lt;/html&gt;</pre>
 192  
 193      <p>Hitting <a href="feed.2.php" shape="rect">feed.2.php</a> you will note
 194      that the <code>{$name}</code> variable reference in the template file is
 195      replaced by the value provided to the <code>set()</code> method in the
 196      controller. Straightforward, no?</p>
 197  
 198      <h3>Think local, not global</h3>
 199  
 200      <p>Unfortunately the world didn't come knocking. Perhaps a little more
 201        personalisation is required? <code>feed.3.php</code>:</p>
 202  
 203      <pre xml:space="preserve">
 204  &lt;?php
 205  require_once '../wact/framework/common.inc.php'; /* Your path to WACT may differ... */
 206  require_once WACT_ROOT . 'template/template.inc.php'; /* Include the base WACT template system */
 207  
 208  $feed =& new Template('/hello-world.3.html'); /* generate a template object from a template file */
 209  $feed->display();               /* display the rendered template */
 210  ?&gt;</pre>
 211  
 212      <p>We lost the call to the <code>set()</code> method, and the template file
 213        has changed, <code>templates/source/hello-world.3.html</code>:</p>
 214  
 215      <pre xml:space="preserve">
 216  &lt;html&gt;
 217  &lt;body&gt;
 218  &lt;core:import file="hello.ini"/&gt;
 219  &lt;h1&gt;Hello, {$location}!&lt;/h1&gt;
 220  &lt;h2&gt;From &amp;ldquo;{$name}&amp;rdquo;.&lt;/h2&gt;
 221  &lt;/body&gt;
 222  &lt;/html&gt;</pre>
 223  
 224      <p>We've introduced another variable reference, <code>{$location}</code>,
 225      but the main thing here is the use of the <code><a
 226      href="http://wact.sourceforge.net/index.php/CoreImportTag"
 227      shape="rect">&lt;core:import/&gt;</a></code> element.</p>
 228  
 229      <p>This WACT element can be used to pull in a dictionary of key-value pairs
 230        from a file (<code>templates/source/hello.ini</code> here). The entries
 231        are stored in the familiar <code>php.ini</code> syntax,
 232        <code>templates/source/hello.ini</code>:</p>
 233  
 234      <pre xml:space="preserve">
 235  location = wherever here is
 236  name = Your name here</pre>
 237  
 238      <p>The import implicitly calls the <code>Template::set()</code> method for
 239      each value, so you can go ahead and use the keys as variable references in
 240      your template.</p>
 241  
 242      <p>If you check out <a href="feed.3.php" shape="rect">feed.3.php</a> after
 243      customising <code>hello.ini</code> appropiately you will get amazing,
 244      personalised, localised output!</p>
 245  
 246      <h2>Feed me up!</h2>
 247  
 248      <p>Ok, ok. Heeeere we go.</p>
 249  
 250      <p>Now remember, syndication feeds generally have a set of headers, followed
 251        by collection of newsworthy(!) items. The header information isn't likely
 252        to change much, so we're going to use the <code>&lt;core:import/&gt;</code>
 253        element and <code>Template::set()</code> to deal with it.</p>
 254  
 255      <h3>From template to shining, validating feed&hellip;</h3>
 256  
 257      <p>Firstly, the template, <code>templates/source/rss1-0.1.rdf</code>:</p>
 258  
 259      <pre xml:space="preserve">
 260  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
 261  &lt;core:import file="rss1-0.ini"/&gt;
 262  &lt;rdf:RDF
 263  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 264  xmlns="http://purl.org/rss/1.0/"
 265  xmlns:dc="http://purl.org/dc/elements/1.1/" &gt;
 266  
 267    &lt;channel rdf:about='{$feedlink}'&gt;
 268      &lt;title&gt;{$feedtitle|utf8encode}&lt;/title&gt;
 269      &lt;link&gt;{$feedlink}&lt;/link&gt;
 270      &lt;description&gt;{$feeddescription|utf8encode}&lt;/description&gt;
 271      &lt;dc:language&gt;{$feedlanguage}&lt;/dc:language&gt;
 272      &lt;dc:date&gt;{$feedpublicationdate}&lt;/dc:date&gt;
 273      &lt;dc:creator&gt;{$feedcreator|utf8encode}&lt;/dc:creator&gt;
 274      &lt;dc:subject&gt;{$feedsubject|utf8encode}&lt;/dc:subject&gt;
 275    &lt;/channel&gt;
 276  
 277  &lt;/rdf:RDF&gt;</pre>
 278  
 279      <p>Check out the <a href="http://web.resource.org/rss/1.0/" shape="rect">RSS
 280      1.0 specification</a> for full details of the format.</p>
 281  
 282      <p>You'll notice quite a few variable references in there
 283      (<code>{$feedlink}, {$feedlanguage}</code> etc.).</p>
 284      <p>What's new here is the use of "output expressions" like 
 285      <code>{$feedtitle|utf8encode}</code>. This particular
 286      example encodes the output with PHP's 
 287      <a href="http://www.php.net/utf8_encode">utf8_encode()</a>
 288      function. See the <a href="http://wact.sourceforge.net/index.php/TemplateAuthorsGuide">
 289      Template Authors Guide</a> for more information on output expressions.</p>
 290      <p>There's also a
 291      <code>&lt;core:import/&gt;</code> tag to import a dictionary from
 292      <code>templates/source/rss1-0.ini</code>:</p>
 293  
 294      <pre xml:space="preserve">
 295  feedlink = http://www.example.com/myfeed
 296  feedtitle = My cool feed
 297  feeddescription = All kinds of ultra-cool stuff
 298  feedlanguage = en-GB
 299  feedcreator = me@example.com
 300  feedsubject = Cool stuff from me</pre>
 301  
 302      <p>The import takes care of most of the variable references, but there are a
 303        couple that we have to deal with in our controller,
 304        <code>feed.4.php</code>:</p>
 305  
 306      <pre xml:space="preserve">
 307  &lt;?php
 308  require_once '../wact/framework/common.inc.php'; /* Your path to WACT may differ... */
 309  require_once WACT_ROOT . 'template/template.inc.php'; /* Include the base WACT template system */
 310  
 311  $feed =& new Template('/rss1-0.1.rdf'); /* generate a template object from a template file */
 312  
 313  /* set the feed publication date (i.e. now) */
 314  putenv("TZ=UTC");
 315  $tstamp = strftime("%Y-%m-%dT%H:%M:%SZ");
 316  $feed->set('feedpublicationdate', $tstamp);
 317  
 318  /* set the content type to get nicer output in browsers 
 319     plus set the character set to utf-8 for i18n chars   */
 320  header("Content-Type: application/xml; charset=utf-8");
 321  $feed->display();               /* display the rendered template */
 322  ?&gt;
 323      </pre>
 324  
 325      <p>We have to set the <code>&lt;?xml version="1.0"?&gt;</code> header
 326      &mdash; PHP has problems with the &lt? if we include it directly in the
 327      template. The only other variable that we set from the controller is
 328      <code>{$feedpublicationdate}</code>.</p>
 329  
 330      <p>As it currently stands, <a href="feed.4.php" shape="rect">feed.4.php</a>,
 331      this sample feed <a href="http://feedvalidator.org/"
 332      shape="rect">validates</a>, but it's a bit dull &mdash; where's the
 333      content?</p>
 334  
 335      <h2>Items, schmitems</h2>
 336  
 337      <p>RSS 1.0 provides it's content as a simple list of items. Well, actually
 338      there are two lists.</p>
 339  
 340      <ul>
 341        <li>One list is stored in the channel element. This list is just a menu of
 342          the <em>items du jour</em>; each item is identified with an
 343          <code>rdf:resource</code> &mdash; a unique identifier (a <acronym
 344          title="Universal Resource Indicator">URI</acronym>, normally the
 345          permalink to the item).</li>
 346  
 347        <li>The second list provides the meat of the dish as a series of
 348          <code>item</code> elements, each containing a <code>title</code>, a
 349          <code>link</code> (the same URI as the <code>rdf:resource</code> from
 350          the menu) and a <code>description</code>. Items may also contain other
 351          optional elements (check the spec for more details).</li>
 352      </ul>
 353  
 354      <h3>So, lists you say&hellip;</h3>
 355  
 356      <p>Time to introduce another WACT element or two &mdash;
 357        <code>&lt;list:list&gt;</code> and its child,
 358        <code>&lt;list:item&gt;</code>. We'll also have to check out <a
 359        href="http://wact.sourceforge.net/index.php/ArrayDataSet"
 360        shape="rect">ArrayDataSets</a>.</p>
 361  
 362      <p>A WACT ArrayDataSet is a <a
 363          href="http://wact.sourceforge.net/index.php/RecordSet"
 364          shape="rect">RecordSet</a> &mdash; it implements the <a
 365          href="http://wact.sourceforge.net/index.php/DataSource"
 366          shape="rect">DataSource</a> interface and a standard <a
 367          href="http://wact.sourceforge.net/index.php/Iterator"
 368          shape="rect">Iterator</a> interface. WACT treats an ArrayDataSet in the
 369          same way that it treats recordsets coming from a database, i.e. as a
 370          collection of DataSpace records that it can iterate through using the
 371          common iterator interface.</p>
 372  
 373      <p>This behaviour allows us to cheat for our feed example, by using an
 374        ArrayDataSet to represent our collection of items. In reality (<em>and
 375        possibly in future versions of this tutorial</em>) this item list would
 376        probably come from a database, or some other persistent storage
 377        mechanism. But for now we'll take the easy route.</p>
 378  
 379      <h3>Cheater</h3>
 380  
 381      <p>We'll set up the ArrayDataSet in our controller,
 382      <code>feed.5.php</code>:</p>
 383  
 384      <pre xml:space="preserve">
 385  &lt;?php
 386  require_once '../wact/framework/common.inc.php'; /* Your path to WACT may differ... */
 387  require_once WACT_ROOT . 'template/template.inc.php'; /* Include the base WACT template system */
 388  require_once WACT_ROOT . 'util/arraydataset.inc.php'; /* Include WACT ArrayDataSet */
 389  
 390  $items_array = array(0 =&gt; array('itemlink' =&gt; 'http://www.example.com/item.1',
 391                  'itemtitle' =&gt; 'The first item in my feed.',
 392                  'itemdescription' =&gt; "This is the first item in my rilly cool feed. Don't you agree, it is very cool?"),
 393               1 =&gt; array('itemlink' =&gt; 'http://www.example.com/item.2',
 394                  'itemtitle' =&gt; 'The second item in my feed.',
 395                  'itemdescription' =&gt; 'Like I say, this feed is just so cool.'),
 396               2 =&gt; array('itemlink' =&gt; 'http://www.example.com/item.3',
 397                  'itemtitle' =&gt; 'The third item in my feed.',
 398                  'itemdescription' =&gt; 'I feel like I have a lot to offer. Oh by the way, Hello, World!'));
 399  $items_recordset =& new ArrayDataSet($items_array);
 400  
 401  
 402  $feed =& new Template('/rss1-0.2.rdf'); /* generate a template object from a template file */
 403  
 404  /* set the feed publication date (i.e. now) */
 405  putenv("TZ=UTC");
 406  $tstamp = strftime("%Y-%m-%dT%H:%M:%SZ");
 407  $feed-&gt;set('feedpublicationdate', $tstamp);
 408  
 409  /* set up the items lists */
 410  $items_menu =& $feed-&gt;getChild('itemsmenu');
 411  $items_menu-&gt;registerDataSet($items_recordset);
 412  $items =& $feed-&gt;getChild('items');
 413  $items-&gt;registerDataSet($items_recordset);
 414  
 415  /* set the content type to get nicer output in browsers 
 416     plus set the character set to utf-8 for i18n chars   */
 417  header("Content-Type: application/xml; charset=utf-8");
 418  $feed-&gt;display();               /* display the rendered template */
 419  ?&gt;</pre>
 420  
 421      <p>Things to note:</p>
 422  
 423      <ul>
 424        <li><code>$items_array</code> contains our multi-dimensional array of
 425        records. Individual records are stored in a dictionary as key-value
 426        pairs.</li>
 427  
 428        <li>We create a new ArrayDataSet, <code>$items_recordset</code> and
 429        populate it with <code>$items_array</code>.</li>
 430  
 431        <li><code>getChild($id)</code> finds the element in our template that has
 432        an id attribute with the value <code>$id</code>, in this case a couple of
 433        <code>&lt;list:list&gt;</code> elements. We can then call
 434        <code>registerDataSet()</code> on each of the elements that we found.</li>
 435  
 436        <li><code>registerDataSet($dataset)</code> does what it says it's going to
 437        do &mdash; it associates our ArrayDataSet as a data provider with our
 438        lists. WACT lists iterate over recordsets for their output as a standard
 439        part of their behaviour.</li>
 440      </ul>
 441  
 442      <h2>Show me the magic</h2>
 443  
 444      <p>Let's take a look at our revised template file,
 445      <code>templates/source/rss1-0.2.rdf</code>:</p>
 446  
 447      <pre xml:space="preserve">
 448  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
 449  &lt;core:import file="rss1-0.ini"/&gt;
 450  &lt;rdf:RDF
 451  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 452  xmlns="http://purl.org/rss/1.0/"
 453  xmlns:dc="http://purl.org/dc/elements/1.1/" &gt;
 454  
 455    &lt;channel rdf:about='{$feedlink}'&gt;
 456      &lt;title&gt;{$feedtitle|utf8encode}&lt;/title&gt;
 457      &lt;link&gt;{$feedlink}&lt;/link&gt;
 458      &lt;description&gt;{$feeddescription|utf8encode}&lt;/description&gt;
 459      &lt;dc:language&gt;{$feedlanguage}&lt;/dc:language&gt;
 460      &lt;dc:date&gt;{$feedpublicationdate}&lt;/dc:date&gt;
 461      &lt;dc:creator&gt;{$feedcreator|utf8encode}&lt;/dc:creator&gt;
 462      &lt;dc:subject&gt;{$feedsubject|utf8encode}&lt;/dc:subject&gt;
 463  
 464      &lt;items&gt;
 465        &lt;rdf:Seq&gt;
 466        &lt;list:list id='itemsmenu'&gt;
 467      &lt;list:item&gt;
 468      &lt;rdf:li rdf:resource="{$itemlink}" /&gt;
 469      &lt;/list:item&gt;
 470        &lt;/list:list&gt;
 471        &lt;/rdf:Seq&gt;
 472      &lt;/items&gt;
 473  
 474    &lt;/channel&gt;
 475  
 476    &lt;list:list id='items'&gt;
 477    &lt;list:item&gt;
 478    &lt;item rdf:about="{$itemlink}"&gt;
 479      &lt;title&gt;{$itemtitle|utf8encode}&lt;/title&gt;
 480      &lt;link&gt;{$itemlink}&lt;/link&gt;
 481      &lt;description&gt;{$itemdescription|utf8encode}&lt;/description&gt;
 482    &lt;/item&gt;
 483    &lt;/list:item&gt;
 484    &lt;/list:list&gt;
 485  
 486  &lt;/rdf:RDF&gt;</pre>
 487  
 488      <p>Well, we've added a couple of WACT lists. Each list is contained in a
 489      <code>&lt;list:list&gt;</code> element, and each item of the list is
 490      contained by a <code>&lt;list:item&gt;</code> element. Within the list item,
 491      variables are referenced just as they are in the other parts of the
 492      template. The WACT magic comes in in that the variable references resolve to
 493      the records within the ArrayDataSet &mdash; <code>&lt;list:list&gt;</code>
 494      is a simple-to-use loop construct for your templates.</p>
 495  
 496      <h3>Bringing home the bacon</h3>
 497  
 498      <p>We'll hit <a href="feed.5.php" shape="rect">feed.5.php</a> and we'll see
 499      what we shall see. Hmmm, interesting.</p>
 500  
 501      <p>The feed <a href="http://feedvalidator.org/" shape="rect">still
 502      validates</a>, so we're obviously doing something right.</p>
 503  
 504      <p>Viewing the feed from an aggregator also produces the output we expected
 505      &mdash; that's our RSS 1.0 feed finished! Easy-peasy.</p>
 506  
 507      <p><img src="straw-small.png" alt="The proof is in the pudding"/>
 508      </p>
 509  
 510      <p>Now all we have to do is create some compelling, original content!</p>
 511  
 512      <h2><span class="strike">Inconclusion</span> In conclusion</h2>
 513  
 514      <p>Hopefully this gentle introduction to WACT has given you the confidence
 515      to produce Enterprise Grade Applications using the framework. Well, maybe
 516      not quite yet&hellip;</p>
 517  
 518      <p>There are a lot of possible improvements to make to this setup, two
 519      obvious ones:</p>
 520  
 521      <ul>
 522        <li>You could provide feeds in alternate formats, perhaps using the HTTP
 523        <code>Accept:</code> header to determine which format to serve up to a
 524        particular user-agent.</li>
 525  
 526        <li>You could look at cacheing the output &mdash; all those aggregators
 527        hitting your <em>ne plus ultra</em> feed regularly could bring your server
 528        to its knees if you rely on dynamic generation.</li>
 529      </ul>
 530  
 531      <p><a href="../" shape="rect">Tutorials Home</a></p>
 532  
 533      <hr/>
 534  
 535      <p>If you use WACT, please contribute to the <a
 536      href="http://wact.sourceforge.net" shape="rect">Wiki</a> as you learn about
 537      it. See the <code>README</code> file in the root of the distribution
 538      for other pointers on further information.</p>
 539  
 540      <hr/>
 541  
 542      <p>Copyright &copy; 2003 Jon Ramsey</p>
 543      <p>
 544        Permission is granted to copy, distribute and/or modify this document
 545        under the terms of the GNU Free Documentation License, Version 1.2 or any
 546        later version published by the Free Software Foundation; with no Invariant
 547        Sections, no Front-Cover Texts, and no Back-Cover Texts.  A copy of the
 548        license is available in the file <a href="../fdl.txt"
 549        shape="rect">fdl.txt</a>.
 550      </p>
 551  
 552    </body>
 553  </html>


Generated: Sun Nov 28 19:36:09 2004 Cross-referenced by PHPXref 0.5