blob: e6ccbe6396d6a2d8a81d11b4ef8dab79839f53f5 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="Apache Forrest" name="Generator">
<meta name="Forrest-version" content="0.9-dev">
<meta name="Forrest-skin-name" content="pelt">
<title>Part 3: Anatomy of the pipeline</title>
<link type="text/css" href="../../../skin/basic.css" rel="stylesheet">
<link media="screen" type="text/css" href="../../../skin/screen.css" rel="stylesheet">
<link media="print" type="text/css" href="../../../skin/print.css" rel="stylesheet">
<link type="text/css" href="../../../skin/profile.css" rel="stylesheet">
<script src="../../../skin/getBlank.js" language="javascript" type="text/javascript"></script><script src="../../../skin/getMenu.js" language="javascript" type="text/javascript"></script><script src="../../../skin/fontsize.js" language="javascript" type="text/javascript"></script>
<link rel="shortcut icon" href="../../../favicon.ico">
</head>
<body onload="init()">
<script type="text/javascript">ndeSetTextSize();</script>
<div id="top">
<!--+
|breadtrail
+-->
<div class="breadtrail">
<a href="http://www.apache.org/">apache</a> &gt; <a href="http://lenya.apache.org/">lenya</a><script src="../../../skin/breadcrumbs.js" language="JavaScript" type="text/javascript"></script>
</div>
<!--+
|header
+-->
<div class="header">
<!--+
|start group logo
+-->
<div class="grouplogo">
<a href=""><img class="logoImage" alt="Lenya" src="../../../images/apache-lenya-light.png" title=""></a>
</div>
<!--+
|end group logo
+-->
<!--+
|start Project Logo
+-->
<div class="projectlogo">
<a href=""></a>
</div>
<!--+
|end Project Logo
+-->
<!--+
|start Search
+-->
<div class="searchbox">
<form action="http://www.google.com/search" method="get" class="roundtopsmall">
<input value="lenya.apache.org" name="sitesearch" type="hidden"><input onFocus="getBlank (this, 'Search the site with ');" size="25" name="q" id="query" type="text" value="Search the site with ">&nbsp;
<input name="Search" value="Search" type="submit">
</form>
</div>
<!--+
|end search
+-->
<!--+
|start Tabs
+-->
<ul id="tabs">
<li>
<a class="unselected" href="../../../index.html">Project</a>
</li>
<li>
<a class="unselected" href="../../../docs/index.html">Developer</a>
</li>
<li>
<a class="unselected" href="../../../community/index.html">Community</a>
</li>
<li>
<a class="unselected" href="../../../docs/2_0_x/index.html">Version 2.0</a>
</li>
<li class="current">
<a class="selected" href="../../../docs/1_2_x/index.html">Version 1.2</a>
</li>
</ul>
<!--+
|end Tabs
+-->
</div>
</div>
<div id="main">
<div id="publishedStrip">
<!--+
|start Subtabs
+-->
<div id="level2tabs"></div>
<!--+
|end Endtabs
+-->
<script type="text/javascript"><!--
document.write("Last Published: " + document.lastModified);
// --></script>
</div>
<!--+
|breadtrail
+-->
<div class="breadtrail">
&nbsp;
</div>
<!--+
|start Menu, mainarea
+-->
<!--+
|start Menu
+-->
<div id="menu">
<div onclick="SwitchMenu('menu_selected_1.1', '../../../skin/')" id="menu_selected_1.1Title" class="menutitle" style="background-image: url('../../../skin/images/chapter_open.gif');">Version 1.2</div>
<div id="menu_selected_1.1" class="selectedmenuitemgroup" style="display: block;">
<div class="menuitem">
<a href="../../../docs/1_2_x/index.html">Index</a>
</div>
<div onclick="SwitchMenu('menu_1.1.2', '../../../skin/')" id="menu_1.1.2Title" class="menutitle">Installation</div>
<div id="menu_1.1.2" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/installation/index.html">Download</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/installation/subversion.html">Subversion Access</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/installation/source_version.html">Install Instructions</a>
</div>
</div>
<div onclick="SwitchMenu('menu_selected_1.1.3', '../../../skin/')" id="menu_selected_1.1.3Title" class="menutitle" style="background-image: url('../../../skin/images/chapter_open.gif');">Tutorial</div>
<div id="menu_selected_1.1.3" class="selectedmenuitemgroup" style="display: block;">
<div class="menuitem">
<a href="../../../docs/1_2_x/tutorial/index.html">Introduction</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/tutorial/understanding_lenya.html">1. Understanding Lenya</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/tutorial/installing_lenya.html">2. Installing Lenya</a>
</div>
<div class="menupage">
<div class="menupagetitle">3. Anatomy of the Pipeline</div>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/tutorial/editing_in_lenya.html">4. Editing in Lenya</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/tutorial/custom_navigation.html">5. Custom Navigation in Lenya</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/tutorial/mod_proxy_and_lenya.html">6a. Mod Proxy and Lenya</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/tutorial/mod_proxy_and_lenya_continued.html">6b. Mod Proxy and Lenya</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.4', '../../../skin/')" id="menu_1.1.4Title" class="menutitle">How-To</div>
<div id="menu_1.1.4" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/faq.html">FAQ</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/new_publication.html">New Publication</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/deploy_publication.html">Deploy Publication</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/look_and_feel.html">Look and Feel</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/custom_resourcetype.html">Custom Resource Type</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/new_mime_type.html">Adding Mime Types</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/site_navigation.html">Site Navigation</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/ldap_authentication.html">LDAP Authentication</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/cms_menus.html">CMS Menus</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/cms_screens.html">CMS Screens</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/search.html">Search Publications</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/external_data.html">External Data</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/how-to/unittests.html">Unit Tests</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5', '../../../skin/')" id="menu_1.1.5Title" class="menutitle">Components</div>
<div id="menu_1.1.5" class="menuitemgroup">
<div onclick="SwitchMenu('menu_1.1.5.1', '../../../skin/')" id="menu_1.1.5.1Title" class="menutitle">Access&nbsp;Control</div>
<div id="menu_1.1.5.1" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/accesscontrol/terms.html">Basic Terms</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/accesscontrol/accesscontrollers.html">Access&nbsp;Controllers</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/accesscontrol/accesscontrollerresolvers.html">Access Controller Resolvers</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/accesscontrol/authenticators.html">Authenticators</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/accesscontrol/authorizers.html">Authorizers</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/accesscontrol/policymanagers.html">Policies and Policy&nbsp;Managers</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/accesscontrol/accreditablemanagers.html">Accreditable&nbsp;Managers</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/accesscontrol/ssl.html">SSL Encryption</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.2', '../../../skin/')" id="menu_1.1.5.2Title" class="menutitle">Authoring</div>
<div id="menu_1.1.5.2" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/authoring/adding-document-creator.html">Adding a new document creator</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/authoring/image-upload.html">Image Upload</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/authoring/openoffice.html">OpenOffice</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.3', '../../../skin/')" id="menu_1.1.5.3Title" class="menutitle">Deployment</div>
<div id="menu_1.1.5.3" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/deployment/proxying.html">Proxying</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.4', '../../../skin/')" id="menu_1.1.5.4Title" class="menutitle">Editors</div>
<div id="menu_1.1.5.4" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/editors/htmlform.html">HTML Form Editor</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/editors/1form.html">HTML One Form Editor</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/editors/bxe.html">Bitflux Editor</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/editors/kupu.html">Kupu</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/editors/xopus.html">Xopus</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.5', '../../../skin/')" id="menu_1.1.5.5Title" class="menutitle">Layout</div>
<div id="menu_1.1.5.5" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/layout/navigation.html">Navigation</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/layout/xhtml-templating.html">XHTML templating</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/layout/static-resources.html">Serving static resources</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/layout/lenya-menubar.html">Lenya Menubar</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.6', '../../../skin/')" id="menu_1.1.5.6Title" class="menutitle">Publication</div>
<div id="menu_1.1.5.6" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/publication/pageenvelopemodule.html">PageEnvelopeModule</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/publication/siteTree.html">Site tree</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.7', '../../../skin/')" id="menu_1.1.5.7Title" class="menutitle">Resource&nbsp;Types</div>
<div id="menu_1.1.5.7" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/resource-types/resource-types.html">Resource&nbsp;Types</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.8', '../../../skin/')" id="menu_1.1.5.8Title" class="menutitle">Revision Control</div>
<div id="menu_1.1.5.8" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/revisioncontrol/revisioncontroller.html">Revision Controller</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/revisioncontrol/rcml.html">RCML</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/revisioncontrol/checkin.html">Check In</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/revisioncontrol/checkout.html">Check Out</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/revisioncontrol/version.html">Revisions</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/revisioncontrol/rollback.html">Rollback</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.9', '../../../skin/')" id="menu_1.1.5.9Title" class="menutitle">Repository</div>
<div id="menu_1.1.5.9" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/repository/index.html">WebDAV Servers</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.10', '../../../skin/')" id="menu_1.1.5.10Title" class="menutitle">Search</div>
<div id="menu_1.1.5.10" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/search/lucene.html">Searching with Lucene</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.11', '../../../skin/')" id="menu_1.1.5.11Title" class="menutitle">URI Handling</div>
<div id="menu_1.1.5.11" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/uri-handling/URIParametrizer.html">URI Parametrizer</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/uri-handling/standardURI.html">URI Scheme</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/uri-handling/usecases.html">Usecases</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.12', '../../../skin/')" id="menu_1.1.5.12Title" class="menutitle">Asset Management</div>
<div id="menu_1.1.5.12" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/asset-management/management.html">Asset Management</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.13', '../../../skin/')" id="menu_1.1.5.13Title" class="menutitle">Link Management</div>
<div id="menu_1.1.5.13" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/link-management/link-management.html">Link Management</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.14', '../../../skin/')" id="menu_1.1.5.14Title" class="menutitle">Meta Data</div>
<div id="menu_1.1.5.14" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/metadata/metadata.html">Meta Data Handling</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.15', '../../../skin/')" id="menu_1.1.5.15Title" class="menutitle">Multilingual Documents</div>
<div id="menu_1.1.5.15" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/multilingual/multilingual.html">Multilingual Document Handling</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.16', '../../../skin/')" id="menu_1.1.5.16Title" class="menutitle">Tasks</div>
<div id="menu_1.1.5.16" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/concept.html">The Task Concept</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/defining.html">Defining Tasks</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/taskaction.html">The TaskAction</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/scheduling.html">Scheduling a Task</a>
</div>
<div onclick="SwitchMenu('menu_1.1.5.16.5', '../../../skin/')" id="menu_1.1.5.16.5Title" class="menutitle">Included tasks</div>
<div id="menu_1.1.5.16.5" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/anttask.html">AntTask</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/publisher.html">DefaultFilePublisher</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/exporter.html">StaticHTMLExporter</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/mailtask.html">MailTask</a>
</div>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/tasks/development.html">Developing Tasks</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.17', '../../../skin/')" id="menu_1.1.5.17Title" class="menutitle">Workflow</div>
<div id="menu_1.1.5.17" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/workflow/terms.html">Terms</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/workflow/state-machine.html">The State Machine</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/workflow/configuration.html">Configuration</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/workflow/implementation.html">Implementation</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5.18', '../../../skin/')" id="menu_1.1.5.18Title" class="menutitle">Site Management</div>
<div id="menu_1.1.5.18" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/archive.html">Archive</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/copy.html">Copy</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/deactivate.html">Deactivate</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/delete.html">Delete</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/deletetrash.html">Delete the trash</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/move.html">Move</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/moveupdown.html">Move Up/Down</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/rename.html">Rename</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/components/sitemanagement/restore.html">Restore</a>
</div>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.6', '../../../skin/')" id="menu_1.1.6Title" class="menutitle">Miscellaneous</div>
<div id="menu_1.1.6" class="menuitemgroup">
<div class="menuitem">
<a href="../../../docs/1_2_x/misc/namespaces.html">Namespaces</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/misc/reserved_names.html">Reserved Names</a>
</div>
<div class="menuitem">
<a href="../../../docs/1_2_x/misc/xinclude-processor.html">XInclude Processor</a>
</div>
</div>
<div class="menuitem">
<a href="../../../apidocs/1.2/index.html">1.2 API (Javadoc)</a>
</div>
</div>
<div id="credit"></div>
<div id="roundbottom">
<img style="display: none" class="corner" height="15" width="15" alt="" src="../../../skin/images/rc-b-l-15-1body-2menu-3menu.png"></div>
<!--+
|alternative credits
+-->
<div id="credit2">
<a href="http://wiki.apache.org/lenya/MeetingFreiburg2008"><img border="0" title="Meeting Freiburg 2008" alt="Meeting Freiburg 2008 - logo" src="../../../images/apache-lenya-meeting-freiburg-2008.png" style="width: 160px;height: 40px;"></a>
</div>
</div>
<!--+
|end Menu
+-->
<!--+
|start content
+-->
<div id="content">
<div title="Portable Document Format" class="pdflink">
<a class="dida" href="anatomy_of_the_pipeline.pdf"><img alt="PDF -icon" src="../../../skin/images/pdfdoc.gif" class="skin"><br>
PDF</a>
</div>
<h1>Part 3: Anatomy of the pipeline</h1>
<div id="front-matter">
<div id="minitoc-area">
<ul class="minitoc">
<li>
<a href="#what_are_pipelines">What are pipelines?</a>
</li>
<li>
<a href="#minimum_requirements">Minimum Requirements</a>
</li>
<li>
<a href="#how_about_something_more_usable">How about something more usable?</a>
</li>
<li>
<a href="#the_lenya_pipeline">The Lenya pipeline</a>
</li>
<li>
<a href="#the_matcher">The Matcher</a>
</li>
<li>
<a href="#the_aggregator">The Aggregator</a>
</li>
<li>
<a href="#the_transformer">The Transformer</a>
</li>
<li>
<a href="#the_selector">The Selector</a>
</li>
<li>
<a href="#the_serializer">The Serializer</a>
</li>
<li>
<a href="#fin">Fin</a>
</li>
</ul>
</div>
</div>
<p>With Lenya installed, you're itching to figure out how to get around this thing so
you can start creating a website. But, you want to put it all together the way
you're used to. Well, bring out the frozen dinners, because this is not your
momma's cooking. Instead of opening up a file, adding our HTML, and throwing in
some CSS, we'll be working with pipelines, XML, XSLT to get the job done.</p>
<a name="N10011"></a><a name="what_are_pipelines"></a>
<h2 class="h3">What are pipelines?</h2>
<div class="section">
<p>Pipelines aren't a Lenya thing - it's a Cocoon thing. If you want to master Lenya,
you'll have to get your hands around Cocoon, and that's not an easy thing. Let me
remind you that the articles we write here are not because I'm an expert in Lenya or
Cocoon. Far from it. But, we have learned some things along the way that we see being
asked over and over, so we think it's important to keep the open-source spirit
alive and document what I've learned.</p>
<p>OK, so back to pipelines. Pipelines are basically part of a set of items that can be
found in a sitemap of your publication, which include the components, views,
resources, etc. We'll save all those for another time. Pipelines are a way to
match a request coming to your publication and act on them in some way. So, for
example, if you are accessing a particular page within your publication using
your web browser, a pipeline can find a match for that request and possibly send
back a page for you to view.</p>
</div>
<a name="N1001C"></a><a name="minimum_requirements"></a>
<h2 class="h3">Minimum Requirements</h2>
<div class="section">
<p>For a pipeline to work, you'll need to match an incoming request, generate
something to be used, and then send it back in a format that is recognizable and can
be dealt with easily. Here's an example pipeline:</p>
<pre class="code">
1. &lt;map:pipeline&gt;
2. &lt;map:match pattern="example"&gt;
3. &lt;map:generate type="file" src="example.xml"/&gt;
4. &lt;map:serialize type="xml"/&gt;
5. &lt;/map:match&gt;
6. &lt;/map:pipeline&gt;
</pre>
<p>Let's walk through this line by line. Line 1 starts the definition of the pipeline.
Everything starts with "map:" because all of this XML is part of the map namespace
defined by Cocoon. Line 2 tries to match an incoming request to see if it looks like
"example". If it does, we keep going. If not, this pipeline gets skipped over.
Line 3 is the generator. In this case, we'll be generating "stuff" from a file, and
that file is example.xml. So, what do we do with this stuff inside the file? Well,
we need to send it back to the user making the request for "example" in something
they (or it) can understand. In line 4, we're doing just that by using a serializer
to take all that stuff in example.xml and sending back to the user as XML.</p>
</div>
<a name="N1002B"></a><a name="how_about_something_more_usable"></a>
<h2 class="h3">How about something more usable?</h2>
<div class="section">
<p>OK, admittedly, that was a boring example. The file was already XML, so the only
thing the serializer did was probably add in our declaration at the top of the page
and send it back to the user. Let's add in some spice and relate it to web pages:</p>
<pre class="code">
1. &lt;map:pipeline&gt;
2. &lt;map:match pattern="test.html"&gt;
3. &lt;map:generate type="file" src="test.xml"/&gt;
4. &lt;map:transform type="xslt" src="test2html.xsl"/&gt;
5. &lt;map:serialize type="html"/&gt;
6. &lt;/map:match&gt;
7. &lt;/map:pipeline&gt;
</pre>
<p>OK, so here, we're trying to match the request for test.html. Now, keep in mind, it
could very well be that test.html doesn't exist (and in this case it doesn't).
That's OK - we're just matching requests for something, and in return, we can send
back whatever we like. Think of it as a virtual link to another file we're creating
on the fly.</p>
<p>So, if we do match test.html, we'll grab the contents of the file test.xml, but
before we send it back, we'll transform that XML into something else using the
transformer (line 4). Using XSLT, we can convert that batch of XML into an HTML
page! That's done using the file test2html.xsl. When that's all said and done,
off we go to serialize it back to the user, but this time as HTML instead of XML.</p>
<p>We won't have time to show you how the XSL transformation works, but we can throw you
over to
<a href="http://www.w3schools.com/xsl/xsl_languages.asp">
W3Schools</a> and they'll give you a nice intro.</p>
</div>
<a name="N10044"></a><a name="the_lenya_pipeline"></a>
<h2 class="h3">The Lenya pipeline</h2>
<div class="section">
<p>So now that we know the basics, how does Lenya use the pipeline in creating it's
pages? Well, it's not too much different. While it looks more complicated, the
basics are still there.</p>
<p>Below is the pipeline that is used in the publication-sitemap.xmap file in
Lenya's default publication:</p>
<pre class="code">
1. &lt;map:pipeline&gt;
2. &lt;!--/lenyabody-{rendertype}/{publication-id}/{area}/{doctype}/{url}--&gt;
3. &lt;map:match pattern="lenyabody-*/*/*/*/**"&gt;
4. &lt;map:aggregate element="cmsbody"&gt;
5. &lt;map:part src="cocoon://navigation/{2}/{3}/breadcrumb/{5}.xml"/&gt;
6. &lt;map:part src="cocoon://navigation/{2}/{3}/tabs/{5}.xml"/&gt;
7. &lt;map:part src="cocoon://navigation/{2}/{3}/menu/{5}.xml"/&gt;
8. &lt;map:part src="cocoon://navigation/{2}/{3}/search/{5}.xml"/&gt;
9. &lt;map:part src="cocoon:/lenya-document-{1}/{3}/{4}/{page-envelope:document-path}"/&gt;&gt;
10.&lt;/map:aggregate&gt;
11.&lt;map:transform src="xslt/page2xhtml-{4}.xsl"&gt;
12.&lt;map:parameter name="root" value="{page-envelope:context-prefix}/{2}/{3}"/&gt;
13.&lt;map:parameter name="url" value="{5}"/&gt;
14.&lt;map:parameter name="document-id" value="{page-envelope:document-id}"/&gt;
15.&lt;map:parameter name="document-type" value="{page-envelope:document-type}"/&gt;
16.&lt;/map:transform&gt;
17.&lt;map:select type="parameter"&gt;
18.&lt;map:parameter name="parameter-selector-test" value="{1}"/&gt;
19.&lt;map:when test="view"&gt;
20.&lt;map:transform type="link-rewrite"/&gt;
21.&lt;/map:when&gt;
22.&lt;/map:select&gt;
23.&lt;map:serialize type="xml"/&gt;
24.&lt;/map:match&gt;
25.&lt;/map:pipeline&gt;
</pre>
<p>OK, yikes, we know what you're thinking. But seriously, it's not that bad. We still
open with a pipeline tag, we match something, we have this aggregation part which
I'll explain in a minute, we transform the results, and after another part I'll
explain, we serialize the results back the user. Let's start with the
matcher.</p>
</div>
<a name="N10056"></a><a name="the_matcher"></a>
<h2 class="h3">The Matcher</h2>
<div class="section">
<p>So, um, what exactly are we matching? Without going into too much and getting you
swamped with terminology, we're basically trying to match a whole bunch of
things at once. The comment right above the matcher tries to tell you what each of
the asterisks are. There's the rendertype (whether you're viewing the page, or
editing it), the publication ID (which in this case is "default" for the Default
Publication), the area (it could be Authoring, or Live, or Admin, etc.), the
document type, and the actual URL of the document.</p>
<p>The document type is pretty interesting. In XML, one document could be for
describing a shape, while another could be describing a set of books. It doesn't
have to be that way, though. For example, the "homepage" and "xhtml" doctypes
provided for you in Lenya are exactly the same, except there's another pipeline
that says the top index.html page of the publication will be assigned the doctype
of "homepage". It's handy because since most homepages have a different design
that the secondary or tertiary pages, you can use a different XSLT file to
transform it however you want without having to setup a new pipeline for it. Just
think of the possibilities with different doctypes...</p>
</div>
<a name="N10061"></a><a name="the_aggregator"></a>
<h2 class="h3">The Aggregator</h2>
<div class="section">
<p>So, after we've matched all of those options (the asterisks mean anything and
everything), we get to this aggregate tag. Basically, it's a generator like we
saw in the previous examples, it's just aggregating the results of the
generation from all these sources together as one.</p>
<p>So, Lenya separates out the menu (or navigation of the site), the tabs (all the
high-level items in the navigation), the breadcrumb trails on the pages, the
search box, and the actual content of the page into separate files. See all those
{2}'s, {3}'s, and {5}'s? Each one of those points to the value for that numbered
asterisk in the matcher. So, whatever happened to have been in the second
asterisk in the matcher, we use that in place of {2}. Simple, no?</p>
</div>
<a name="N1006C"></a><a name="the_transformer"></a>
<h2 class="h3">The Transformer</h2>
<div class="section">
<p>The transformer is pretty straight-forward. We transform the results of all the
aggregated content using the file page2xhtml-{4}.xsl. Except, the {4} is
replaced with whatever was in the place of the fourth asterisk, or in this case,
the doctype. So, if our doctype was "homepage", we would transform our page using
the XSL file page2xhtml-homepage.xsl. If our doctype were "xhtml" (which is
what most of the pages are in Lenya), then you would transform it with
page2xhtml-xhtml.xsl. See how you can differentiate the design with different
transformations and doctypes?</p>
<p>The parameters inside of the transform tag are basically setting up variables to
be passed to the XSL file. In this case, we're passing along the root location of
the publication (perhaps it's just a / in http://www.someplace.com/, for
example), the URL of the publication (like "some/where.html"), as well as the
document ID (the latter half of the URL without the .html extension), and the
doctype.</p>
</div>
<a name="N10077"></a><a name="the_selector"></a>
<h2 class="h3">The Selector</h2>
<div class="section">
<p>We haven't seen this one yet, but think of the selector as an if/else statement. You
have to tell the selector what you are testing against, then test it against some
value, and do something. In this case, we're testing the rendertype (that's the
first asterisk, or {1}). If the rendertype is "view", as in we're viewing the page
and not editing it, then go through one more transformation, called
link-rewrite.</p>
<p>The link-rewrite transformer basically checks where you are, then goes through
the contents of the page and rewrites all links in relation to what area you are in.
For example, if we are in the Authoring environment in Lenya, then our links could be
rewritten to look like "/lenya/default/authoring/some/where.html". If we are
in the Live area, they would be rewritten to look like
"/lenya/default/live/some/where.html". That way, you just keep track of the
organization of the site using the Site tab within Lenya, and Lenya will rewrite
your links according to what area you are in when viewing the page so that it all
just works!</p>
</div>
<a name="N10082"></a><a name="the_serializer"></a>
<h2 class="h3">The Serializer</h2>
<div class="section">
<p>In the end, we serialize everything we've done into XML. So, why XML? Because it's
later on in the series of pipelines that the results are serialized again into
HTML (or XHTML, if you so choose).</p>
</div>
<a name="N1008A"></a><a name="fin"></a>
<h2 class="h3">Fin</h2>
<div class="section">
<p>So hopefully that gets you cracking on understanding how Lenya is setup to handle
pages. There's no doubt we've exposed you to quite a bit that deserves more
explanation, and it will certainly come.</p>
</div>
</div>
<!--+
|end content
+-->
<div class="clearboth">&nbsp;</div>
</div>
<div id="footer">
<!--+
|start bottomstrip
+-->
<div class="lastmodified">
<script type="text/javascript"><!--
document.write("Last Published: " + document.lastModified);
// --></script>
</div>
<div class="copyright">
Copyright &copy;
2002-2007 <a href="http://www.apache.org/licenses/LICENSE-2.0">The Apache Software Foundation.</a>
</div>
<div id="feedback">
Send feedback about the website to:
<a id="feedbackto" href="mailto:dev@lenya.apache.org?subject=Feedback%C2%A0for%C2%A0docs/1_2_x/tutorial/anatomy_of_the_pipeline.html">dev@lenya.apache.org</a>
</div>
<!--+
|end bottomstrip
+-->
</div>
</body>
</html>