| <!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.8-dev"> |
| <meta name="Forrest-skin-name" content="pelt"> |
| <title>Forrest Sitemap Reference (v0.8-dev)</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> > <a href="http://forrest.apache.org/">forrest</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="http://www.apache.org/"><img class="logoImage" alt="Apache" src="../images/apache-forrest.png" title="The Apache Software Foundation"></a> |
| </div> |
| <!--+ |
| |end group logo |
| +--> |
| <!--+ |
| |start Project Logo |
| +--> |
| <div class="projectlogo"> |
| <a href="http://forrest.apache.org/"><img class="logoImage" alt="Forrest" src="../images/project-logo.gif" title="Apache Forrest"></a> |
| </div> |
| <!--+ |
| |end Project Logo |
| +--> |
| <!--+ |
| |start Search |
| +--> |
| <div class="searchbox"> |
| <form action="http://www.google.com/search" method="get" class="roundtopsmall"> |
| <input value="forrest.apache.org" name="sitesearch" type="hidden"><input onFocus="getBlank (this, 'Search the site with google');" size="25" name="q" id="query" type="text" value="Search the site with google"> |
| <input name="Search" value="Search" type="submit"> |
| </form> |
| </div> |
| <!--+ |
| |end search |
| +--> |
| <!--+ |
| |start Tabs |
| +--> |
| <ul id="tabs"> |
| <li> |
| <a class="unselected" href="../index.html">Welcome</a> |
| </li> |
| <li> |
| <a class="unselected" href="../contrib.html">Developers</a> |
| </li> |
| <li class="current"> |
| <a class="selected" href="../versions/index.html">Versioned Docs</a> |
| </li> |
| <li> |
| <a class="unselected" href="../pluginDocs/index.html">Plugins</a> |
| </li> |
| <li> |
| <a class="unselected" href="../tools/index.html">Tools</a> |
| </li> |
| </ul> |
| <!--+ |
| |end Tabs |
| +--> |
| </div> |
| </div> |
| <div id="main"> |
| <div id="publishedStrip"> |
| <!--+ |
| |start Subtabs |
| +--> |
| <div id="level2tabs"> |
| <a class="unselected" href="../docs_0_70/index.html">0.70 (current)</a><a class="selected" href="../docs_0_80/index.html">0.80-dev (under development)</a><a class="unselected" href="../docs_0_60/index.html">0.60 (past)</a> |
| </div> |
| <!--+ |
| |end Endtabs |
| +--> |
| <script type="text/javascript"><!-- |
| document.write("Last Published: " + document.lastModified); |
| // --></script> |
| </div> |
| <!--+ |
| |breadtrail |
| +--> |
| <div class="breadtrail"> |
| |
| |
| </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');">0.80-dev</div> |
| <div id="menu_selected_1.1" class="selectedmenuitemgroup" style="display: block;"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/index.html">Overview</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/your-project.html">Using Forrest</a> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.3', '../skin/')" id="menu_1.1.3Title" class="menutitle">How-To</div> |
| <div id="menu_1.1.3" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/index.html">Overview</a> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.3.2', '../skin/')" id="menu_1.1.3.2Title" class="menutitle">Install Forrest</div> |
| <div id="menu_1.1.3.2" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/build.html" title="Build and install the current unreleased version">Building Forrest from Source</a> |
| </div> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/upgrading_08.html">Upgrading to 0.8</a> |
| </div> |
| <div class="menuitem"> |
| <a href="">Use Forrest</a> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.3.5', '../skin/')" id="menu_1.1.3.5Title" class="menutitle">Customize Forrest</div> |
| <div id="menu_1.1.3.5" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/sitemap-explain.html">Sitemaps explained</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/howto-custom-html-source.html">Custom html source</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/project-sitemap.html">Project sitemap</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/howto-editcss.html">Edit CSS (WYSIWYG)</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/howto-pdf-tab.html" title="Generate one pdf-document for all pages of a tab">Create tab PDF</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/howto-corner-images.html">CSS corner SVG</a> |
| </div> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.3.6', '../skin/')" id="menu_1.1.3.6Title" class="menutitle">Integrate Forrest with tools</div> |
| <div id="menu_1.1.3.6" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/howto-forrest-from-maven.html">Maven Integration</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/catalog.html">Using DTD Catalogs</a> |
| </div> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.3.7', '../skin/')" id="menu_1.1.3.7Title" class="menutitle">Extend Forrest</div> |
| <div id="menu_1.1.3.7" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/howto-buildPlugin.html">Build a Plugin</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/skin-package.html">Package new Skins</a> |
| </div> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/howto-asf-mirror.html">Download mirror</a> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.3.9', '../skin/')" id="menu_1.1.3.9Title" class="menutitle">Adding Documentation</div> |
| <div id="menu_1.1.3.9" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../howto-howto.html" title="Instructions for writing a new howto-document">Write a How-to</a> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.3.9.2', '../skin/')" id="menu_1.1.3.9.2Title" class="menutitle">Multipage HowTo</div> |
| <div id="menu_1.1.3.9.2" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/multi/howto-multi.html">Introduction</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/multi/step1.html">Step 1</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/multi/step2.html">Step 2</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/multi/step3.html">Step 3</a> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/faq.html">FAQs</a> |
| </div> |
| <div onclick="SwitchMenu('menu_selected_1.1.5', '../skin/')" id="menu_selected_1.1.5Title" class="menutitle" style="background-image: url('../skin/images/chapter_open.gif');">Background</div> |
| <div id="menu_selected_1.1.5" class="selectedmenuitemgroup" style="display: block;"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/linking.html">Menus and Linking</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/searching.html">Search Options in Forrest</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/locationmap.html">Locationmap</a> |
| </div> |
| <div class="menupage"> |
| <div class="menupagetitle">Sitemap Reference</div> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/skins.html" title="About default skins, their naming and features">Skins</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/status-themes.html">Dispatcher versus Skins</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/cap.html">Sourcetype Action</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/validation.html">XML validation and entity resolution</a> |
| </div> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/changes.html">Changes</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/glossary.html">Glossary</a> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.8', '../skin/')" id="menu_1.1.8Title" class="menutitle">Reference docs</div> |
| <div id="menu_1.1.8" class="menuitemgroup"> |
| <div onclick="SwitchMenu('menu_1.1.8.1', '../skin/')" id="menu_1.1.8.1Title" class="menutitle">DTD documentation</div> |
| <div id="menu_1.1.8.1" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../dtdx/dtd-docs.html">Overview</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../dtdx/document-v20.dtdx.html">document-v20</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../dtdx/howto-v20.dtdx.html">howto-v20</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../dtdx/faq-v20.dtdx.html">faq-v20</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../dtdx/document-v13.dtdx.html">document-v13</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../dtdx/howto-v13.dtdx.html">howto-v13</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../dtdx/faq-v13.dtdx.html">faq-v13</a> |
| </div> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.8.2', '../skin/')" id="menu_1.1.8.2Title" class="menutitle">Doc samples</div> |
| <div id="menu_1.1.8.2" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../dtdx/document-v13.html">document-v13</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../dtdx/document-v20.html">document-v20</a> |
| </div> |
| </div> |
| </div> |
| <div onclick="SwitchMenu('menu_1.1.9', '../skin/')" id="menu_1.1.9Title" class="menutitle">Older Docs</div> |
| <div id="menu_1.1.9" class="menuitemgroup"> |
| <div class="menuitem"> |
| <a href="../docs_0_80/primer.html">Forrest Primer</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/libre-intro.html">Libre</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/dreams.html">Dream list</a> |
| </div> |
| <div class="menuitem"> |
| <a href="../docs_0_80/howto/cvs-ssh/howto-cvs-ssh.html">CVS over SSH</a> |
| </div> |
| </div> |
| </div> |
| <div id="credit"> |
| <hr> |
| This is documentation for development version v0.8 |
| (<a href="http://forrest.apache.org/versions/">More</a>)</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://apachecon.com/2007/EU/"><img border="0" title="ApacheCon Europe 2007" alt="ApacheCon Europe 2007 - logo" src="http://apache.org/ads/ApacheCon/2007-europe-125x125.png" style="width: 125px;height: 125px;"></a><a href="http://people.apache.org/calendar.html#200711"><img border="0" title="ApacheCon US 2007" alt="ApacheCon US 2007 - logo" src="http://apache.org/ads/ApacheCon/2007-usa-125x125.png" style="width: 125px;height: 125px;"></a> |
| </div> |
| </div> |
| <!--+ |
| |end Menu |
| +--> |
| <!--+ |
| |start content |
| +--> |
| <div id="content"> |
| <div title="Portable Document Format" class="pdflink"> |
| <a class="dida" href="sitemap-ref.pdf"><img alt="PDF -icon" src="../skin/images/pdfdoc.gif" class="skin"><br> |
| PDF</a> |
| </div> |
| <div class="trail">Font size: |
| <input value="Reset" class="resetfont" title="Reset text" onclick="ndeSetTextSize('reset'); return false;" type="button"> |
| <input value="-a" class="smallerfont" title="Shrink text" onclick="ndeSetTextSize('decr'); return false;" type="button"> |
| <input value="+a" class="biggerfont" title="Enlarge text" onclick="ndeSetTextSize('incr'); return false;" type="button"> |
| </div> |
| <h1>Forrest Sitemap Reference</h1> |
| <div id="motd-area"> |
| This is documentation for development version v0.8 |
| (<a href="http://forrest.apache.org/versions/">More</a>)</div> |
| <div id="minitoc-area"> |
| <ul class="minitoc"> |
| <li> |
| <a href="#getting_started">Getting started</a> |
| </li> |
| <li> |
| <a href="#overview">Sitemap Overview</a> |
| </li> |
| <li> |
| <a href="#source_pipelines">Source pipelines (**.xml)</a> |
| <ul class="minitoc"> |
| <li> |
| <a href="#forrest_xmap">forrest.xmap</a> |
| </li> |
| <li> |
| <a href="#other_source">Other source pipelines</a> |
| <ul class="minitoc"> |
| <li> |
| <a href="#late_binding_pipelines">Late-binding pipelines</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li> |
| <a href="#output_pipelines">Output pipelines</a> |
| <ul class="minitoc"> |
| <li> |
| <a href="#pdf">PDF output</a> |
| </li> |
| <li> |
| <a href="#html">HTML output</a> |
| </li> |
| </ul> |
| </li> |
| <li> |
| <a href="#intermediate_pipelines">Intermediate pipelines</a> |
| <ul class="minitoc"> |
| <li> |
| <a href="#body_pipeline">Page body</a> |
| </li> |
| <li> |
| <a href="#menu_pipeline">Page menu</a> |
| </li> |
| <li> |
| <a href="#tab_pipeline">Page tabs</a> |
| </li> |
| </ul> |
| </li> |
| <li> |
| <a href="#resolvingResources">Resolving Resources</a> |
| </li> |
| <li> |
| <a href="#menu_generation_impl">Menu XML generation</a> |
| </li> |
| <li> |
| <a href="#linkrewriting_impl">Link rewriting</a> |
| <ul class="minitoc"> |
| <li> |
| <a href="#input_modules">Cocoon foundations: Input Modules</a> |
| </li> |
| <li> |
| <a href="#implement_rewriting">Implementing "site:" rewriting</a> |
| <ul class="minitoc"> |
| <li> |
| <a href="#cocoon_xconf">cocoon.xconf</a> |
| </li> |
| <li> |
| <a href="#sitemap">sitemap.xmap</a> |
| </li> |
| <li> |
| <a href="#dynamic_linkmap">Dynamically generating a linkmap</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| |
| <p> |
| Technically, Forrest can be thought of as a |
| <a href="http://cocoon.apache.org/2.1/">Cocoon</a> distribution that has been stripped |
| down and optimized for people with simple site publishing needs. Central |
| to Cocoon, and hence Forrest, is the <strong>sitemap</strong>. The sitemap |
| defines the site's URI space (what pages are available), and how each page |
| is constructed. Understanding the sitemap is the key to understanding |
| Forrest. |
| </p> |
| |
| <div class="note"> |
| <div class="label">Note</div> |
| <div class="content"> |
| We advise you to spend time to understand the Apache Cocoon sitemap. See |
| <a href="http://cocoon.apache.org/2.1/userdocs/concepts/sitemap.html">Cocoon sitemap</a> and |
| <a href="http://cocoon.apache.org/2.1/userdocs/concepts/">Cocoon concepts</a> and related |
| component documentation. It is also necessary to understand the "**" and |
| "*" pattern matching and replacements. See the email thread: "Re: explain |
| sitemap matches and pass parameters to transformers" |
| <a href="http://issues.apache.org/jira/browse/FOR-874">FOR-874</a>. |
| </div> |
| </div> |
| |
| <p> |
| This document provides an overview of the special sitemap which is used at |
| the core of Apache Forrest. |
| </p> |
| |
| <div class="warning"> |
| <div class="label">Warning</div> |
| <div class="content"> |
| The example sitemap fragments might be out-of-date because since this |
| document was written, the core sitemaps in main/webapp/ have changed and |
| some of the specialised processing has moved to plugins. View your source |
| sitemaps when reading this document. (See |
| <a href="https://issues.apache.org/jira/browse/FOR-922">FOR-922</a>.) |
| </div> |
| </div> |
| |
| <a name="N10030"></a><a name="getting_started"></a> |
| <h2 class="underlined_10">Getting started</h2> |
| <div class="section"> |
| <p> |
| Forrest's sitemap comprises the multiple |
| $FORREST_HOME/main/webapp/*.xmap files. The main one is |
| <strong>sitemap.xmap</strong> which delegates to others, including to |
| sitemaps in the various |
| <a href="../pluginDocs/plugins_0_80/pluginInfrastructure.html">plugins</a>. |
| </p> |
| <p> |
| You can add pre-processing sitemaps to your project |
| <span class="codefrag">src/documentation</span> directory (or wherever |
| <span class="codefrag">${project.sitemap-dir}</span> points to). Any match that is not |
| handled, passes through to be handled by the default Forrest sitemaps - |
| obviously extremely powerful. The capability is described in |
| "<a href="../docs_0_80/project-sitemap.html">Using project sitemaps</a>". |
| </p> |
| <p> |
| Another way to experiment with the sitemap is to do '<span class="codefrag">forrest |
| run</span>' on a Forrest-using site. Making changes to the core |
| <span class="codefrag">*.xmap</span> files will now be immediately effective at |
| <span class="codefrag">http://localhost:8888/</span> |
| |
| </p> |
| </div> |
| |
| <a name="N1005A"></a><a name="overview"></a> |
| <h2 class="underlined_10">Sitemap Overview</h2> |
| <div class="section"> |
| <p> |
| Forrest's sitemap is divided both physically and logically. The most |
| obvious is the physical separation. There are a number of separate |
| *.xmap files, each defining pipelines for a functional area. Each *.xmap |
| file has its purpose documented in comments at the top. Here is a brief |
| overview of the files, in order of importance. |
| </p> |
| <table class="ForrestTable" cellspacing="1" cellpadding="4"> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1"><strong>sitemap.xmap</strong> |
| </th> |
| <td colspan="1" rowspan="1">Primary sitemap file, which delegates responsibility for serving |
| certain URIs to the others (technically called sub-sitemaps). More |
| about the structure of this file later.</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">forrest.xmap</th> |
| <td colspan="1" rowspan="1">Sitemap defining Source pipelines, which generate the body section |
| of Forrest pages. All pipelines here deliver XML in Forrest's |
| intermediate "document-v13" format, regardless of originating source |
| or format.</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">menu.xmap</th> |
| <td colspan="1" rowspan="1">Pipelines defining the XML that becomes the menu.</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">linkmap.xmap</th> |
| <td colspan="1" rowspan="1">Defines a mapping from abstract ("site:index") to physical |
| ("index.html") links for the current page. See |
| <a href="../docs_0_80/linking.html">Menus and Linking</a> for a conceptual |
| overview, and the <a href="#linkrewriting_impl">Link |
| rewriting</a> section for technical details.</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">resources.xmap</th> |
| <td colspan="1" rowspan="1">Serves "resource" files (images, CSS, Javascript).</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">raw.xmap</th> |
| <td colspan="1" rowspan="1">Serves files located in <span class="codefrag">src/documentation/content/xdocs</span> |
| that are not to be modified by Forrest.</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">aggregate.xmap</th> |
| <td colspan="1" rowspan="1">Generates a single page (HTML or PDF) containing all the content |
| for the site.</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">faq.xmap</th> |
| <td colspan="1" rowspan="1">Processes FAQ documents.</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">status.xmap</th> |
| <td colspan="1" rowspan="1">Generates <a href="../docs_0_80/changes.html">changes</a> and |
| <a href="../todo.html">todo</a> pages from a single |
| <span class="codefrag">status.xml</span> in the project root. |
| </td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">issues.xmap</th> |
| <td colspan="1" rowspan="1">Generates a page of content from an RSS feed. Used in Forrest to |
| generate a "current issues" list from JIRA.</td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">revisions.xmap</th> |
| <td colspan="1" rowspan="1"> |
| Support for HOWTO documents that want "revisions". Revisions are |
| XML snippets containing comments on the main XML file. The main |
| pipeline here automatically appends a page's revisions to the |
| bottom. |
| </td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">dtd.xmap</th> |
| <td colspan="1" rowspan="1">A Source pipeline that generates XML from a DTD, using Andy |
| Clark's |
| <a href="http://www.apache.org/~andyc/neko/doc/dtd/index.html">DTD |
| Parser</a>. Useful for documenting DTD-based XML schemas, such |
| as <a href="../docs_0_80/../dtdx/dtd-docs.html">Forrest's own DTDs</a>. |
| </td> |
| |
| </tr> |
| |
| <tr> |
| |
| <th colspan="1" rowspan="1">profiler.xmap</th> |
| <td colspan="1" rowspan="1">Defines the "profiler" pipeline. allowing pipelines to be benchmarked.</td> |
| |
| </tr> |
| |
| </table> |
| </div> |
| <!-- |
| <section> |
| <title>Logical structure</title> |
| <p>There are a few major groups of sitemap pipelines</p> |
| <dl> |
| <dt>Content pipelines</dt> |
| <dd>These define the body (without menu and header) for HTML pages, and all the content of PDFs.</dd> |
| <dt>Menu pileines. |
| </dl> |
| </section> |
| --> |
| |
| <a name="N10132"></a><a name="source_pipelines"></a> |
| <h2 class="underlined_10">Source pipelines (**.xml)</h2> |
| <div class="section"> |
| <p> |
| Most *.xmap files (forrest, aggregate, faq, status, issues, revisions, |
| dtd) define Source pipelines. Source pipelines define the content (body) |
| XML for site pages. The input XML format can be any format |
| (document-v13, Docbook, RSS, FAQ, Howto) and from any source (local or |
| remote). The output format is always Forrest's intermediate |
| "document-v13" format. |
| </p> |
| <p> |
| Source pipelines always have a "<span class="codefrag">.xml</span>" extension. Thus, |
| <a href="index.xml">index.xml</a> gives you the XML source for the |
| index page. Likewise, <a href="faq.xml">faq.xml</a> gives you XML |
| for the FAQ (transformed from FAQ syntax), and |
| <a href="changes.xml">changes.xml</a> returns XML from the |
| status.xml file. Take any page, and replace its extension |
| (<span class="codefrag">.html</span> or <span class="codefrag">.pdf</span>) with <span class="codefrag">.xml</span> and |
| you'll have the Source XML. |
| </p> |
| <p> |
| This is quite powerful, because we now have an abstraction layer, or |
| "virtual filesystem", on which the rest of Forrest's sitemap can build. |
| Subsequent layers don't need to care whether the XML was obtained |
| locally or remotely, or from what format. Wikis, RSS, FAQs and Docbook |
| files are all processed identically from here on. |
| </p> |
| <pre class="code"> |
| (subsequent Forrest pipelines) |
| | |
| --------+------------------------^------------------------------------------ |
| | STANDARD FORREST FORMAT (current document-v13) |
| +-----^-------^--------^------------^------^-----^-----^------^----- |
| SOURCE | | | | | | | | |
| FORMATS doc-v11 doc-v13 doc-v20 ... Docbook FAQ Howto Wiki RSS ?? |
| (*.xml) |
| (in forrest.xmap, faq.xmap, etc) |
| </pre> |
| <a name="N1015D"></a><a name="forrest_xmap"></a> |
| <h3 class="underlined_5">forrest.xmap</h3> |
| <p> |
| Most of the usual Source pipelines are defined in |
| <span class="codefrag">forrest.xmap</span> which is the default (fallback) handler for |
| <span class="codefrag">**.xml</span> pages. The forrest.xmap uses the |
| <a href="../docs_0_80/cap.html">SourceTypeAction</a> to determine the type of |
| XML it is processing, and converts it to document-v13 if necessary. |
| </p> |
| <p> |
| For instance, say we are rendering <a href="../howto-howto.html">a |
| Howto document</a> called "howto-howto.xml". It contains this |
| DOCTYPE declaration: |
| </p> |
| <pre class="code"> |
| <!DOCTYPE howto PUBLIC "-//APACHE//DTD How-to V1.3//EN" |
| "http://forrest.apache.org/dtd/howto-v13.dtd"></pre> |
| <p> |
| The SourceTypeAction sees this, and applies this transform to get it |
| to document-v13: |
| </p> |
| <pre class="code"> |
| |
| <map:when test="howto-v13"> |
| <map:transform src="{forrest:forrest.stylesheets}/howto-to-document.xsl" /> |
| </map:when> |
| |
| </pre> |
| <a name="N10185"></a><a name="other_source"></a> |
| <h3 class="underlined_5">Other source pipelines</h3> |
| <p> |
| As mentioned above, all non-core Source pipelines are distributed in |
| independent <span class="codefrag">*.xmap</span> files. There is a block of |
| <span class="codefrag">sitemap.xmap</span> which simply delegates certain requests to |
| these subsitemaps: |
| </p> |
| <pre class="code"> |
| |
| <!-- Body content --> |
| <map:match pattern="**.xml"> |
| <map:match pattern="changes.xml"> |
| <map:mount uri-prefix="" src="status.xmap" check-reload="yes" /> |
| </map:match> |
| |
| <map:match pattern="todo.xml"> |
| <map:mount uri-prefix="" src="status.xmap" check-reload="yes" /> |
| </map:match> |
| |
| <map:match pattern="**dtdx.xml"> |
| <map:mount uri-prefix="" src="dtd.xmap" check-reload="yes" /> |
| </map:match> |
| |
| <map:match pattern="forrest-issues.xml"> |
| <map:mount uri-prefix="" src="issues.xmap" check-reload="yes" /> |
| </map:match> |
| |
| <map:match pattern="**faq.xml"> |
| <map:mount uri-prefix="" src="faq.xmap" check-reload="yes" /> |
| </map:match> |
| |
| <map:match pattern="site.xml"> |
| <map:mount uri-prefix="" src="aggregate.xmap" check-reload="yes" /> |
| </map:match> |
| .... |
| .... |
| </pre> |
| <a name="N10198"></a><a name="late_binding_pipelines"></a> |
| <h4>Late-binding pipelines</h4> |
| <p> |
| One point of interest here is that the sub-sitemap is often not |
| specific about which URLs it handles, and relies on the caller (the |
| section listed above) to only pass relevant requests to it. We term |
| this "binding a URL" to a pipeline. |
| </p> |
| <p> |
| For instance, the main pipeline in <span class="codefrag">faq.xmap</span> matches |
| <span class="codefrag">**.xml</span>, but only <span class="codefrag">**faq.xml</span> requests are |
| sent to it. |
| </p> |
| <p> |
| This "late binding" is useful, because the whole URL space is |
| managed in <span class="codefrag">sitemap.xmap</span> and not spread over lots of |
| *.xmap files. For instance, say you wish all <span class="codefrag">*.xml</span> |
| inside a "<span class="codefrag">faq/</span>" directory to be processed as FAQs. Just |
| override <span class="codefrag">sitemap.xmap</span> and redefine the relevant source |
| matcher: |
| </p> |
| <pre class="code"> |
| |
| <map:match pattern="**faq.xml"> |
| <map:mount uri-prefix="" src="faq.xmap" check-reload="yes" /> |
| </map:match> |
| </pre> |
| </div> |
| |
| <a name="N101C3"></a><a name="output_pipelines"></a> |
| <h2 class="underlined_10">Output pipelines</h2> |
| <div class="section"> |
| <p> |
| To recap, we now have a <span class="codefrag">*.xml</span> pipeline defined for each |
| page in the site, emitting standardized XML. These pipeline definitions |
| are located in various *.xmap files, notably forrest.xmap |
| </p> |
| <p> |
| We now wish to render the XML from these pipelines to output formats |
| like HTML and PDF. |
| </p> |
| <a name="N101D2"></a><a name="pdf"></a> |
| <h3 class="underlined_5">PDF output</h3> |
| <div class="note"> |
| <div class="label">Note</div> |
| <div class="content"> |
| PDF is now generated via the org.apache.forrest.plugin.output.pdf |
| plugin. |
| </div> |
| </div> |
| <p> |
| Easiest case first; PDFs don't require menus or headers, so we can |
| simply transform our intermediate format into XSL:FO, and from there |
| to PDF. This is done by the following matcher in |
| <span class="codefrag">output.xmap</span> from the pdf plugin ... |
| </p> |
| <pre class="code"> |
| |
| 1 <map:match type="regexp" pattern="^(.*?)([^/]*).pdf$"> |
| 2 <map:generate src="cocoon:/{1}{2}.xml"/> |
| 3 <map:transform type="xinclude"/> |
| 4 <map:transform type="<a href="#linkrewriting_impl">linkrewriter</a>" src="cocoon://{1}linkmap-{2}.pdf"/> |
| 5 <map:transform src="skins/{forrest:forrest.skin}/xslt/fo/document-to-fo.xsl"> |
| 6 <map:parameter name="ctxbasedir" value="{realpath:.}/"/> |
| 7 <map:parameter name="xmlbasedir" value="content/xdocs/{1}"/> |
| 8 </map:transform> |
| 9 <map:serialize type="fo2pdf"/> |
| 10 </map:match> |
| |
| </pre> |
| <ol> |
| |
| <li>The first line uses a matching regexp to break the URL into |
| directory <span class="codefrag">(.*?)</span> and filename |
| <span class="codefrag">([^/]*)</span> parts.</li> |
| |
| <li>We then generate XML from a <a href="#source_pipelines">Source |
| pipeline</a>, with the URL <span class="codefrag">cocoon:/{1}{2}.xml</span> |
| </li> |
| |
| <li>We then expand any XInclude statements..</li> |
| |
| <li>and <a href="#linkrewriting_impl">rewrite links</a>..</li> |
| |
| <li>and finally apply the document-to-fo.xsl stylesheet, to generate |
| XSL:FO XML.</li> |
| |
| </ol> |
| <p> |
| Lastly, we generate a PDF using the fo2pdf serializer. |
| </p> |
| <a name="N1020F"></a><a name="html"></a> |
| <h3 class="underlined_5">HTML output</h3> |
| <p> |
| Generating HTML pages is more complicated, because we have to merge |
| the page body with a menu and tabs, and then add a header and footer. |
| Here is the <span class="codefrag">*.html</span> matcher in <span class="codefrag">sitemap.xmap</span> |
| ... |
| </p> |
| <pre class="code"> |
| <map:match pattern="*.html"> |
| <map:aggregate element="site"> |
| <map:part src="<a href="#tab_pipeline">cocoon:/tab-{0}</a>"/> |
| <map:part src="<a href="#menu_pipeline">cocoon:/menu-{0}</a>"/> |
| <map:part src="<a href="#body_pipeline">cocoon:/body-{0}</a>"/> |
| </map:aggregate> |
| <map:call resource="skinit"> |
| <map:parameter name="type" value="site2xhtml"/> |
| <map:parameter name="path" value="{0}"/> |
| </map:call> |
| </map:match> |
| </pre> |
| <p> |
| So <a href="index.html">index.html</a> is formed from |
| aggregating <a href="body-index.html">body-index.html</a> and |
| <a href="menu-index.html">menu-index.html</a> and |
| <a href="tab-index.html">tab-index.html</a> and then applying |
| the <span class="codefrag">site-to-xhtml.xsl</span> stylesheet to the result. |
| </p> |
| <p> |
| There is a nearly identical matcher for HTML files in subdirectories: |
| </p> |
| <pre class="code"> |
| <map:match pattern="**/*.html"> |
| <map:aggregate element="site"> |
| <map:part src="<a href="#tab_pipeline">cocoon:/{1}/tab-{2}.html</a>"/> |
| <map:part src="<a href="#menu_pipeline">cocoon:/{1}/menu-{2}.html</a>"/> |
| <map:part src="<a href="#body_pipeline">cocoon:/{1}/body-{2}.html</a>"/> |
| </map:aggregate> |
| <map:call resource="skinit"> |
| <map:parameter name="type" |
| value="site2xhtml"/> |
| <map:parameter name="path" |
| value="{0}"/> |
| </map:call> |
| </map:match> |
| </pre> |
| </div> |
| |
| <a name="N10259"></a><a name="intermediate_pipelines"></a> |
| <h2 class="underlined_10">Intermediate pipelines</h2> |
| <div class="section"> |
| <a name="N1025F"></a><a name="body_pipeline"></a> |
| <h3 class="underlined_5">Page body</h3> |
| <p> |
| Here is the matcher which generates the page body: |
| </p> |
| <pre class="code"> |
| |
| 1 <map:match pattern="**body-*.html"> |
| 2 <map:generate src="cocoon:/{1}{2}.xml"/> |
| 3 <map:transform type="idgen"/> |
| 4 <map:transform type="xinclude"/> |
| 5 <map:transform type="<a href="#linkrewriting_impl">linkrewriter</a>" src="cocoon:/{1}linkmap-{2}.html"/> |
| 6 <map:call resource="skinit"> |
| 7 <map:parameter name="type" value="document2html"/> |
| 8 <map:parameter name="path" value="{1}{2}.html"/> |
| 9 <map:parameter name="notoc" value="false"/> |
| 10 </map:call> |
| 11 </map:match> |
| |
| </pre> |
| <ol> |
| |
| <li>In our matcher pattern, {1} will be the directory (if any) and {2} |
| will be the filename.</li> |
| |
| <li>First, we obtain XML content from a source pipeline</li> |
| |
| <li> |
| <p> |
| We then apply a custom-written |
| <span class="codefrag">IdGeneratorTransformer</span>, which ensures that every |
| <section> has an "id" attribute if one is not supplied, by |
| generating one from the <title> if necessary. For example, |
| <idgen> will transform: |
| </p> |
| |
| <pre class="code"> |
| <section> |
| <title>How to boil eggs</title> |
| ... |
| </pre> |
| |
| <p> |
| into: |
| </p> |
| |
| <pre class="code"> |
| <section id="How+to+boil+eggs"> |
| <title>How to boil eggs</title> |
| ... |
| </pre> |
| |
| <p> |
| Later, the <span class="codefrag">document-to-html.xsl</span> stylesheet will |
| create an <a name> element for every section, allowing this |
| section to be referred to as |
| <span class="codefrag">index.html#How+to+boil+eggs</span>. |
| </p> |
| </li> |
| |
| <li>We then expand XInclude elements.</li> |
| |
| <li>and <a href="#linkrewriting_impl">rewrite links</a>..</li> |
| |
| <li>and then finally apply the stylesheet that generates a fragment of |
| HTML (minus the outer elements like |
| <html> and <body>) suitable for merging with the menu and tabs.</li> |
| |
| </ol> |
| <a name="N102A2"></a><a name="menu_pipeline"></a> |
| <h3 class="underlined_5">Page menu</h3> |
| <p> |
| In the <span class="codefrag">sitemap.xmap</span> file, the matcher generating HTML for |
| the menu is: |
| </p> |
| <pre class="code"> |
| |
| <map:match pattern="**menu-*.html"> |
| <map:generate src="cocoon:/{1}book-{2}.html"/> |
| <map:transform type="<a href="#linkrewriting_impl">linkrewriter</a>" src="cocoon:/{1}linkmap-{2}.html"/> |
| <map:call resource="skinit"> |
| <map:parameter name="type" value="book2menu"/> |
| <map:parameter name="path" value="{1}{2}.html"/> |
| </map:call> |
| </map:match> |
| |
| </pre> |
| <p> |
| We get XML from a "book" pipeline, |
| <a href="#linkrewriting_impl">rewrite links</a>, and apply the |
| <span class="codefrag">book-to-menu.xsl</span> stylesheet to generate HTML. |
| </p> |
| <p> |
| How the menu XML is actually generated (the *book-*.html pipeline) is |
| sufficiently complex to require a |
| <a href="#menu_generation_impl">section of its own</a>. |
| </p> |
| <a name="N102C8"></a><a name="tab_pipeline"></a> |
| <h3 class="underlined_5">Page tabs</h3> |
| <p> |
| Tab generation is quite tame compared to menus: |
| </p> |
| <pre class="code"> |
| |
| <map:match pattern="**tab-*.html"> |
| <map:generate src="content/xdocs/tabs.xml" /> |
| <map:transform type="<a href="#linkrewriting_impl">linkrewriter</a>" src="cocoon:/{1}linkmap-{2}.html"/> |
| <map:call resource="skinit"> |
| <map:parameter name="type" value="tab2menu"/> |
| <map:parameter name="path" value="{1}{2}.html"/> |
| </map:call> |
| </map:match> |
| |
| </pre> |
| <p> |
| All the smarts are in the <span class="codefrag">tab-to-menu.xsl</span> stylesheet, |
| which needs to choose the correct tab based on the current path. |
| Currently, a "longest matching path" algorithm is implemented. See the |
| <span class="codefrag">tab-to-menu.xsl</span> stylesheet for details. |
| </p> |
| </div> |
| |
| <a name="N102E4"></a><a name="resolvingResources"></a> |
| <h2 class="underlined_10">Resolving Resources</h2> |
| <div class="section"> |
| <p> |
| Many resources are resolved by the locationmap. This allow us to provide |
| many alternative locations for a file without cluttering up the sitemap |
| with multiple processing paths. We use a strict naming convention to |
| help make the sitemaps more readable. This is described in the |
| <a href="../docs_0_80/locationmap.html#namingConvention">Locationmap</a> |
| documentation. |
| </p> |
| </div> |
| |
| <a name="N102F2"></a><a name="menu_generation_impl"></a> |
| <h2 class="underlined_10">Menu XML generation</h2> |
| <div class="section"> |
| <p> |
| The "book" pipeline is defined in <span class="codefrag">sitemap.xmap</span>as: |
| </p> |
| <pre class="code"> |
| |
| <map:match pattern="**book-*.html"> |
| <map:mount uri-prefix="" src="menu.xmap" check-reload="yes" /> |
| </map:match> |
| |
| </pre> |
| <p> |
| Meaning that it is defined in the <span class="codefrag">menu.xmap</span> file. In there |
| we find the real definition, which is quite complicated, because there |
| are three supported menu systems (see <a href="../docs_0_80/linking.html">menus |
| and linking</a>). We will not go through the sitemap itself |
| (menu.xmap), but will instead describe the logical steps involved: |
| </p> |
| <ol> |
| |
| <li>Take site.xml and expand hrefs so that they are all |
| root-relative.</li> |
| |
| <li> |
| <p> |
| Depending on the <span class="codefrag">forrest.menu-scheme</span> property, we now |
| apply one of the two algorithms for choosing a set of menu links |
| (described in <a href="../docs_0_80/linking.html#menu_generation">menu |
| generation</a>): |
| </p> |
| |
| <ul> |
| |
| <li> |
| <p> |
| For "@tab" menu generation, we first ensure each site.xml node |
| has a tab attribute (inherited from a parent if necessary), and |
| then pass through nodes whose tab attribute matches that of the |
| "current" node. |
| </p> |
| |
| <p> |
| For example, say our current page's path is |
| <span class="codefrag">community/howto/index.html</span>. In |
| <span class="codefrag">site.xml</span> we look for the node with this |
| "<span class="codefrag">href</span>" and discover its "<span class="codefrag">tab</span>" |
| attribute value is "<span class="codefrag">howtos</span>". We then prune the |
| <span class="codefrag">site.xml</span>-derived content to contain only nodes with |
| <span class="codefrag">tab="howtos"</span>. |
| </p> |
| |
| <p> |
| All this is done with XSLT, so the sitemap snippet does not |
| reveal this complexity: |
| </p> |
| |
| <pre class="code"> |
| |
| <map:transform src="resources/stylesheets/site-to-site-normalizetabs.xsl" /> |
| <map:transform src="resources/stylesheets/site-to-site-selectnode.xsl"> |
| <map:parameter name="path" value="{1}{2}"/> |
| </map:transform> |
| |
| </pre> |
| </li> |
| |
| <li> |
| <p> |
| For "directory" menu generation, we simply use an |
| <span class="codefrag">XPathTransformer</span> to include only pages in the |
| current page's directory, or below: |
| </p> |
| |
| <pre class="code"> |
| |
| <map:transform type="xpath"> |
| <map:parameter name="include" value="//*[@href='{1}']" /> |
| </map:transform> |
| |
| </pre> |
| |
| <p> |
| Here, the "<span class="codefrag">{1}</span>" is the directory part of the |
| current page. So if our current page is |
| <span class="codefrag">community/howto/index.html</span> then "<span class="codefrag">{1}</span>" |
| will be <span class="codefrag">community/howto/</span> and the transformer will |
| include all nodes in that directory. |
| </p> |
| </li> |
| |
| </ul> |
| |
| <p> |
| We now have a <span class="codefrag">site.xml</span> subset relevant to our current |
| page. |
| </p> |
| </li> |
| |
| <li>The "<span class="codefrag">href</span>" nodes in this are then made relative to the |
| current page.</li> |
| |
| <li>The XML is then transformed into a legacy "<span class="codefrag">book.xml</span>" |
| format, for compatibility with existing stylesheets, and this XML |
| format is returned (hence the name of the matcher: |
| <span class="codefrag">**book-*.html</span>).</li> |
| |
| </ol> |
| </div> |
| |
| <a name="N10373"></a><a name="linkrewriting_impl"></a> |
| <h2 class="underlined_10">Link rewriting</h2> |
| <div class="section"> |
| <p> |
| In numerous places in <span class="codefrag">sitemap.xmap</span> you will see the |
| "linkrewriter" transformer in action. For example: |
| </p> |
| <pre class="code"> |
| <map:transform type="linkrewriter" src="cocoon:/{1}linkmap-{2}.html"/> |
| </pre> |
| <p> |
| This statement is Cocoon's linking system in action. A full description |
| is provided in <a href="../docs_0_80/linking.html">Menus and Linking</a>. Here |
| we describe the implementation of linking. |
| </p> |
| <a name="N1038A"></a><a name="input_modules"></a> |
| <h3 class="underlined_5">Cocoon foundations: Input Modules</h3> |
| <p> |
| The implementation of <span class="codefrag">site:</span> linking is heavily based on |
| Cocoon <a href="http://cocoon.apache.org/2.1/userdocs/concepts/modules.html">Input Modules</a>, a |
| little-known but quite powerful aspect of Cocoon. Input Modules are |
| generic Components which simply allow you to look up a value with a |
| key. The value is generally dynamically generated, or obtained by |
| querying an underlying data source. |
| </p> |
| <p> |
| In particular, Cocoon contains an <span class="codefrag">XMLFileModule</span>, which |
| lets one look up the value of an XML node, by interpreting the key as |
| an XPath expression. Cocoon also has a |
| <span class="codefrag">SimpleMappingMetaModule</span>, which allows the key to be |
| rewritten before it is used to look up a value. |
| </p> |
| <p> |
| The idea for putting these together to rewrite "<span class="codefrag">site:</span>" |
| links was described in <a href="http://marc.theaimsgroup.com/?t=103992708800001&r=1&w=2">this |
| thread</a>. The idea is to write a Cocoon Transformer that triggers |
| on encountering <link href="<span class="codefrag">scheme:address</span>">, and |
| interprets the <span class="codefrag">scheme:address</span> internal URI as |
| <span class="codefrag">inputmodule:key</span>. The transformer then uses the named |
| InputModule to look up the key value. The <span class="codefrag">scheme:address</span> |
| URI is then rewritten with the found value. This transformer was |
| implemented as |
| <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=15611">LinkRewriterTransformer</a>, |
| currently distributed as a "block" in Cocoon 2.1 |
| </p> |
| <a name="N103BE"></a><a name="implement_rewriting"></a> |
| <h3 class="underlined_5">Implementing "site:" rewriting</h3> |
| <p> |
| Using the above components, "<span class="codefrag">site:</span>" URI rewriting is |
| accomplished as follows. |
| </p> |
| <a name="N103CD"></a><a name="cocoon_xconf"></a> |
| <h4>cocoon.xconf</h4> |
| <p> |
| First, we declare all the input modules we will be needing: |
| </p> |
| <pre class="code"> |
| |
| <!-- For the site: scheme --> |
| <component-instance |
| class="org.apache.cocoon.components.modules.input.XMLFileModule" |
| logger="core.modules.xml" name="linkmap"/> |
| |
| <!-- Links to URIs within the site --> |
| <component-instance |
| class="org.apache.cocoon.components.modules.input.SimpleMappingMetaModule" |
| logger="core.modules.mapper" name="site"/> |
| |
| <!-- Links to external URIs, as distinct from 'site' URIs --> |
| <component-instance |
| class="org.apache.cocoon.components.modules.input.SimpleMappingMetaModule" |
| logger="core.modules.mapper" name="ext"/> |
| |
| </pre> |
| <ul> |
| |
| <li> |
| <strong>linkmap</strong> will provide access to the contents of |
| <span class="codefrag">site.xml</span>; for example, <span class="codefrag">linkmap:/site/about/index/@href</span> |
| would return the value "index.html".</li> |
| |
| <li> |
| <strong>site</strong> provides a "mask" over |
| <strong>linkmap</strong> such that <span class="codefrag">site:index</span> expands |
| to <span class="codefrag">linkmap:/site//index/@href</span> |
| </li> |
| |
| <li> |
| <strong>ext</strong> provides another "mask" over |
| <strong>linkmap</strong>, such that <span class="codefrag">ext:ant</span> would |
| expand to <span class="codefrag">linkmap:/site/external-refs//ant/@href</span> |
| </li> |
| |
| </ul> |
| <p> |
| However at the moment, we have only declared the input modules. They |
| will be configured in <span class="codefrag">sitemap.xmap</span> as described in the |
| next section. |
| </p> |
| <a name="N10409"></a><a name="sitemap"></a> |
| <h4>sitemap.xmap</h4> |
| <p> |
| Now in the sitemap, we define the LinkRewriterTransformer, and |
| insert it into any pipelines which deal with user-editable XML |
| content: |
| </p> |
| <pre class="code"> |
| |
| .... |
| <!-- Rewrites links, e.g. transforming |
| href="site:index" to href="../index.html" |
| --> |
| <map:transformer name="linkrewriter" |
| logger="sitemap.transformer.linkrewriter" |
| src="org.apache.cocoon.transformation.LinkRewriterTransformer"> |
| <link-attrs>href src</link-attrs> |
| <schemes>site ext</schemes> |
| |
| <input-module name="site"> |
| <input-module name="linkmap"> |
| <file src="{src}" reloadable="false" /> |
| </input-module> |
| <prefix>/site//</prefix> |
| <suffix>/@href</suffix> |
| </input-module> |
| <input-module name="ext"> |
| <input-module name="linkmap"> |
| <file src="{src}" reloadable="false" /> |
| </input-module> |
| <prefix>/site/external-refs//</prefix> |
| <suffix>/@href</suffix> |
| </input-module> |
| </map:transformer> |
| .... |
| .... |
| <map:match pattern="**body-*.html"> |
| <map:generate src="cocoon:/{1}{2}.xml"/> |
| <map:transform type="idgen"/> |
| <map:transform type="xinclude"/> |
| <map:transform type="linkrewriter" src="cocoon:/{1}linkmap-{2}.html"/> |
| ... |
| </map:match> |
| </pre> |
| <p> |
| As you can see, our three input modules are configured as part of |
| the LinkRewriterTransformer's configuration. |
| </p> |
| <ul> |
| |
| <li> |
| <p> |
| Most deeply nested, we have: |
| </p> |
| |
| <pre class="code"> |
| |
| <input-module name="linkmap"> |
| <file src="{src}" reloadable="false" /> |
| </input-module> |
| </pre> |
| |
| <p> |
| The "<span class="codefrag">{src}</span>" text is expanded to the value of the |
| "<span class="codefrag">src</span>" attribute in the "<span class="codefrag">linkrewriter</span>" |
| instance, namely "<span class="codefrag">cocoon:/{1}linkmap-{2}.html</span>" Thus |
| the <span class="codefrag">linkmap</span> module reads dynamically generated XML |
| specific to the current request. |
| </p> |
| </li> |
| |
| <li> |
| <p> |
| One level out, we configure the "<span class="codefrag">site</span>" and |
| "<span class="codefrag">ext</span>" input modules, to map onto our dynamically |
| configured "<span class="codefrag">linkmap</span>" module. |
| </p> |
| </li> |
| |
| <li> |
| <p> |
| Then at the outermost level, we configure the |
| "<span class="codefrag">linkrewriter</span>" transformer. First we tell it which |
| attributes to consider rewriting: |
| </p> |
| |
| <pre class="code"> |
| |
| <link-attrs>href src</link-attrs> |
| <schemes>site ext</schemes> |
| </pre> |
| |
| <p> |
| So, "<span class="codefrag">href</span>" and "<span class="codefrag">src</span>" attributes |
| starting with "<span class="codefrag">site:</span>" or "<span class="codefrag">ext:</span>" are |
| rewritten. |
| </p> |
| |
| <p> |
| By nesting the "<span class="codefrag">site</span>" and "<span class="codefrag">ext</span>" input |
| modules in the "<span class="codefrag">linkrewriter</span>" configuration, we |
| tell "<span class="codefrag">linkrewriter</span>" to use these two input modules |
| when rewriting links. |
| </p> |
| </li> |
| |
| </ul> |
| <p> |
| The end result is that, for example, the source XML for the |
| <span class="codefrag">community/body-index.html</span> page has its links rewritten |
| by an XMLFileModule reading XML from |
| <span class="codefrag">cocoon:/community/linkmap-index.html</span> |
| |
| </p> |
| <a name="N10476"></a><a name="dynamic_linkmap"></a> |
| <h4>Dynamically generating a linkmap</h4> |
| <p> |
| Why do we need this "linkmap" pipeline generating dynamic XML from |
| <span class="codefrag">site.xml</span>, instead of just using <span class="codefrag">site.xml</span> directly? The reasons are described |
| in <a href="http://marc.theaimsgroup.com/?l=forrest-dev&m=103444028129281&w=2">the linkmap RT</a>: we need to |
| concatenate @hrefs and add dot-dots to the paths, depending on which |
| directory the linkee is in. This is done with the following |
| pipelines in <span class="codefrag">linkmap.xmap</span> ... |
| </p> |
| <pre class="code"> |
| |
| <!-- site.xml with @href's appended to be context-relative. --> |
| <map:match pattern="abs-linkmap"> |
| <map:generate src="content/xdocs/site.xml" /> |
| <map:transform src="resources/stylesheets/absolutize-linkmap.xsl" /> |
| <map:serialize type="xml" /> |
| </map:match> |
| |
| <!-- Linkmap for regular pages --> |
| <map:match pattern="**linkmap-*"> |
| <map:generate src="cocoon://abs-linkmap" /> |
| <map:transform src="resources/stylesheets/relativize-linkmap.xsl"> |
| <map:parameter name="path" value="{1}{2}" /> |
| <map:parameter name="site-root" value="{conf:project-url}" /> |
| </map:transform> |
| <map:serialize type="xml" /> |
| </map:match> |
| |
| </pre> |
| <p> |
| You can try these URIs out directly on a live Forrest to see what is |
| going on (for example, Forrest's own |
| <a href="../abs-linkmap">abs-linkmap</a>). |
| </p> |
| </div> |
| |
| </div> |
| <!--+ |
| |end content |
| +--> |
| <div class="clearboth"> </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 © |
| 2002-2007 <a href="http://www.apache.org/licenses/">The Apache Software Foundation.</a> |
| </div> |
| <!--+ |
| |end bottomstrip |
| +--> |
| </div> |
| </body> |
| </html> |