<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns="http://purl.org/rss/1.0/">




    



<channel rdf:about="http://www.treebrolly.com/blog/posts/RSS">
  <title>Treebrolly posts</title>
  <link>http://www.treebrolly.com</link>

  <description>
    
      
    
  </description>

  

  
            <syn:updatePeriod>daily</syn:updatePeriod>
            <syn:updateFrequency>1</syn:updateFrequency>
            <syn:updateBase>2011-03-13T21:11:55Z</syn:updateBase>
        

  <image rdf:resource="http://www.treebrolly.com/logo.png"/>

  <items>
    <rdf:Seq>
      
        <rdf:li rdf:resource="http://www.treebrolly.com/blog/attachments-now-for-the-future"/>
      
      
        <rdf:li rdf:resource="http://www.treebrolly.com/blog/turbo-plone-theming-with-xdv-diazo"/>
      
    </rdf:Seq>
  </items>

</channel>


  <item rdf:about="http://www.treebrolly.com/blog/attachments-now-for-the-future">
    <title>Attachments Now for the Future</title>
    <link>http://www.treebrolly.com/blog/attachments-now-for-the-future</link>
    <description>A simple way to create pages with file attachments in Plone without compromising your site's Deco readiness.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Here's a reasonable requirement of a website:</p>
<p class="callout">Pages can have <em>attachments</em>. Attachments are files associated with a page. They're listed when viewing the page.</p>
<p>In Plone, the upcoming <a class="reference external" href="https://github.com/plone/plone.app.deco/blob/master/README.rst">Deco page layout system</a> promises to make such pages <a class="reference external" href="https://github.com/plone/plone.app.contentlistingtile">very easy to create</a>. But what are the options right now? If we're building a new Plone site today, how do we model attachments in a clean, easy-to-implement way that won't leave cruft when we go Deco?</p>
<div class="section" id="page-attachment-basics">
<h3>Page attachment basics</h3>
<p>Page attachments can help to settle visitors on pages with lots of downloadable files. The idea is that when a file is called an 'attachment' site visitors draw a parallel with the same concept in email. They recognise that the file belongs to its page and is an essential part of the page's content.</p>
<p>Of course the web has no notion of attachment. In HTML an attachment is a link to a file exactly like any other. The only difference is in how the links are named and presented together on the page. We might do something like:</p>
<pre class="literal-block">
&lt;div id=&quot;attachments&quot;&gt;
  &lt;h2&gt;Attachments&lt;/h2&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;tyrannosaurus.pdf&quot;&gt;Tyrannosaurus Full Report&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;stegosaurus.pdf&quot;&gt;Stegosaurus Information Pack&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
</pre>
</div>
<div class="section" id="with-a-little-help-from-my-content-management-system">
<h3>With a little help from my Content Management System</h3>
<p>In Plone we can build a page with attachments simply by uploading a couple of files as <strong>File</strong> objects, then linking to them from a <strong>Page</strong> with the attachments HTML as part of its body text. But writing such HTML by hand is laborious and error-prone. We ask our Content Management System for a little help:</p>
<p class="callout">Content authors can easily add, edit and delete attachments for a page. The system automatically lists those attachments when the page is viewed.</p>
<p>To do this, Plone needs to know which Files are the attachments of a given page - we need the system to model the attachment relationship.</p>
</div>
<div class="section" id="contain-me-not">
<h3>Contain me not</h3>
<p>Attachments are Files that belong to - are contained by - a Page. Is there a way to model that something contains a set of other somethings in Plone? <a class="reference external" href="http://plone.org/documentation/manual/plone-4-user-manual/introduction/conceptual-overview">Yes indeed</a>. One of the first things you learn is that some pieces of content are containers - other items of content are stored inside them. But like an HTML page on the filesystem, the Page type in Plone is not a container. Alas we cannot model attachments as Files contained inside a Page.</p>
</div>
<div class="section" id="contain-me-do-with-deco">
<h3>Contain me do, with Deco</h3>
<p>Yet exciting changes are afoot for Plone's Page type. The upcoming Deco page layout system will introduce <a class="reference external" href="https://github.com/plone/plone.app.page">a Page type that can contain Files</a> and therefore can model attachments through containment. Great! (Note: the Page change is but one small part of Deco). The question is, how do we model attachments today, on a new site, in a way that works now and will be simple to switch to Deco, both technically and for a content author?</p>
</div>
<div class="section" id="richdocument-blues">
<h3>RichDocument blues</h3>
<p>One solution is to install a product like <a class="reference external" href="http://plone.org/products/richdocument">RichDocument</a> or <a class="reference external" href="http://plone.org/products/plonearticle">PloneArticle</a> to gain a page type that supports attachments. RichDocument has been useful for me in the past (once upon a time I was disabling Page in favour of RichDocument by default on new sites) but I've become wary of this approach.</p>
<ul class="simple">
<li>RichDocument's attachment controls are basic. For example, authors can't reorder attachments easily.</li>
<li>Authors have to workaround limitations where RichDocument breaks the usual Plone paradigms. For example, adding an attachment to a newly created (still in the factory) RichDocument won't work unless that page's title has been set, because Plone has to create a (valid) RichDocument first.</li>
<li>Replacing a fundamental component like the Page type with a non-core product effectively forks your site away from - and behind - the path of Plone core. For example, blob storage worked for core File types, but not for the FileAttachment type used in RichDocument (this is <a class="reference external" href="http://pypi.python.org/pypi/Products.SimpleAttachment#changelog">fixed now</a>).</li>
<li>A <a class="reference external" href="http://dev.plone.org/ticket/7529">bug in Iterate</a> causes attachment edits on a RichDocument working copy to 'disappear' on checkin.</li>
<li>RichDocument is Archetypes only. Dexterity types cannot simply model attachments in the same way.</li>
</ul>
<p>The Iterate bug is painful, but Archetypes-only is the big reason to stay away from RichDocument for me. I want a consistent attachments mechanism for Archetypes and Dexterity types.</p>
</div>
<div class="section" id="hacks-and-other-atrocities">
<h3>Hacks and other atrocities</h3>
<p>All we need to do is reference Files from Pages, right? There are some obvious, brute force ways to do that. Unfortunately, none of these are appealing solutions to me:</p>
<dl class="docutils">
<dt>Point to attachment Files in the Page's Related Items field</dt>
<dd>Eugh. Breaks the 'Don't hijack general metadata for hacks' rule. What if I want a related file that is <em>not</em> an attachment?</dd>
<dt>Tag Files in the Subject field with a keyword convention like <tt class="docutils literal">Attached to: Page = dinosaurs</tt></dt>
<dd>As above but more so. No.</dd>
<dt>Add a new 'attachments' ReferenceField (for both Archetypes and Dexterity types)</dt>
<dd>No no no. No hacky metadata full stop! I don't want general content to have explanatory text about when to set this field - it's too much cognitive load for content authors.</dd>
</dl>
<p>The chief problem with all of these is that they're unintuitive. A content author has to remember to take some step to have their attachment show up.</p>
</div>
<div class="section" id="a-happy-medium">
<h3>A happy medium</h3>
<p>What to do then? The solution I've arrived at is to <strong>use a Folder to contain the Page and any Files that are attachments</strong>. In other words we model the relationship with containment after all, only using a Folder as a 'wrapper' object rather than having the Page contain the Files directly.</p>
<p>What I like about this is that it's just good, solid Plone content organisation - Pages, Files and Folders as explained in any Plone reference. The Page has to be set as the default item in the Folder - that's fairly common Plone practice. The Files have to be excluded from navigation - again something regular content authors will find familiar. No extra metadata twiddling is necessary.</p>
<p>However:</p>
<ul class="simple">
<li>It's far from intuitive. After all, I thought it noteworthy enough to warrant a blog post!</li>
<li>Authors must give the Folder and Page the same title for consistency in the navigation.</li>
<li>If attachment display is active (see below) any File in the folder is listed as an attachment, which might not be what's wanted.</li>
<li>It's hard to retrofit attachments to existing Pages. We have to make a Folder and move the Page into it.</li>
<li>Searching for a Page by title will match both the Folder and the Page inside.</li>
</ul>
<p>Display-wise, in my particular case I needed the list of attachments to show up on the right hand side. The obvious candidate was a <strong>portlet</strong>. Considering the options, I realised that a navigation portlet set to display only content at its own level would work great if set up as a Page <strong>content type portlet</strong>. I had to change the renderer to ignore exclusion (remember Files are set excluded from the left hand navigation!) and describe them as 'Attachments'. Being a content type portlet it is created automatically for a new Page (and other attachment-enabled types), but is simple to remove or block if unwanted on a given Page.</p>
<p>I've put together an <a class="reference external" href="https://github.com/danjacka/example.attachments">example.attachments</a> package demonstrating the approach.</p>
</div>
<div class="section" id="conclusion">
<h3>Conclusion</h3>
<p>Often we can satisfy our custom requirements neatly by leveraging features in core Plone. In this case simple container types did the trick. There's a tonne of other useful tools in there too (<strong>workflow</strong>, <strong>content rules</strong> and <strong>nested groups</strong> are among my favourites). Take the time you were going to spend knocking up a quick fix to investigate how to take advantage of a core feature. Long term, your solution will be much more solid.</p>
<p>That Deco is rethinking how some of Plone's fundamental authoring tools work is really exciting to me. It should open up even more ways to elegantly solve customers' problems. That's why I'm starting to think now about how Deco will fit into any new site's lifecycle.</p>
<p>Got another approach for modeling attachments in Plone? Let me know!</p>
</div>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Dan Jacka</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2012-01-03T10:57:01Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://www.treebrolly.com/blog/turbo-plone-theming-with-xdv-diazo">
    <title>Turbo Plone theming with XDV/Diazo</title>
    <link>http://www.treebrolly.com/blog/turbo-plone-theming-with-xdv-diazo</link>
    <description>Want to convince a potential client to switch to Plone? Wow them with a Plone-powered version of their existing site built in a single day.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Remember 1980's so-bad-it's-good <a href="http://en.wikipedia.org/wiki/Flash_Gordon_%28film%29">Flash Gordon</a> movie? In the buildup to the final reel, the damsel in distress implores our hero:</p>
<p class="callout">"Flash, Flash, I love you, but we only have fourteen hours to save the Earth!"</p>
<p>Fourteen hours?! To the eight-year-old me - accustomed to James Bond's mere minutes for bomb diffusal (done with 007 seconds to spare of course) - that was aeons of time in which to rescue mankind. Did <i>anything</i> take that long?</p>
<p>Of course the adult me - website-building me - knows better. Effort for theming alone can be measured in days, even weeks. But here's a thing: what if you could take an existing theme and slide it neatly into place in front of an existing, powerful content management system? Two big blocks of effort already done - all you had to do was tie them together. <b>XDV</b> makes this idea a reality for Plone. You can get results so quickly with XDV that when I set up a Plone 4 demo site for a potential client recently, I was confident that they could have a version of their current site's theme after a single day's development effort. Yep, a deadline one third tighter than Flash Gordon's!</p>
<p>Want to know how? What follows is a step-by-step tutorial explaining what I did. My aim is to give enough detail that someone new to Plone (an inquisitive web designer maybe?) could follow along. At the end I'll give some pointers on growing your demo site into a fully themed, production Plone site.</p>
<h2 id="the-xdv-approach">The XDV approach</h2>
<p>With XDV (or <b>Diazo</b> as it will soon be known) you build up your theme by defining <a href="http://plone.org/products/collective.xdv/documentation/reference-manual/theming/quick-start/how-it-works">how small chunks of markup fit into the overall HTML structure of your page</a>. It's simple to understand but very flexible and powerful. XDV works independent of Plone (see also XDV's older cousin <a href="http://packages.python.org/Deliverance/">Deliverance</a>) but is easy to get running on a Plone site thanks to the <b>collective.xdv</b> package (soon to undergo its own name change to <b>plone.app.theming</b>).</p>
<p>What we need for the demo site are:</p>
<ul>
<li>Plone 4 with collective.xdv installed,</li>
<li>a theme file - a page from the client's current site in a local <i>index.html</i>,</li>
<li>a rules file that defines how XDV should map Plone content into the theme file,</li>
<li>a CSS file with Plone-specific styles; all other styles come from the client's current site,</li>
<li>all of those files wrapped up with a few config tweaks into a <i>client.demo</i> package.</li>
</ul>
<h2 id="getting-started">Getting started</h2>
<p>I can't show you the site I built, so first we need a new client. Hmmm, how about <a href="http://www.number10.gov.uk">the British Prime Minister's Office</a>? The content is a broad and deep tree of standard pages - the stuff an out-of-the-box Plone excels at. Looks like it's currently a Wordpress site.</p>
<p style="text-align: center; "><img class="image-inline" src="../images/n10-screenshot1.png/@@images/image/preview" /></p>
<p>Alright, let's build that.</p>
<p>To install Plone on your machine, follow <a href="http://plone.org/documentation/manual/installing-plone">the standard instructions</a> to build a standalone, non-root instance of Plone 4 at <i>$HOME/Plone</i>. If you're on Linux it's as easy as:</p>
<pre>$ cd
$ wget http://launchpad.net/plone/4.0/4.0.4/+download/Plone-4.0.4-UnifiedInstaller.tgz
$ tar xzvf Plone-4.0.4-UnifiedInstaller.tgz
$ cd Plone-4.0.4-UnifiedInstaller
$  ./install.sh --password=secret standalone</pre>
<p class="callout">You can delete the Unified Installer when you're done. Also, Plone does not install anything outside the <i>$HOME/Plone</i> directory, so if you want to remove your site at a later date just delete that directory.</p>
<p>I want to concentrate on XDV, so for these next few steps I'll give the instructions without much background info. You'll find plenty more detail in <a href="http://plone.org/documentation/">Plone.org's documentation section</a>.</p>
<p>We will store our theme and config files in a package called <b>number10.demo</b>. Let's create a package template with <a href="http://pypi.python.org/pypi/ZopeSkel">ZopeSkel</a>:</p>
<pre>$ cd $HOME/Plone/zinstance
$ pushd src
$ ../bin/zopeskel plone number10.demo</pre>
<p>ZopeSkel will ask a few questions. Hit <i>&lt;Enter&gt;</i> on all of them except 'Register Profile'. Set that as True - we want the package to register a GenericSetup profile.</p>
<pre>$ popd</pre>
<p>Done. number10.demo now exists in the <i>src</i> directory. Next we need to add our new package and the collective.xdv package to the build. Create a file <i>demo.cfg</i> in <i>$HOME/Plone/zinstance</i> containing:</p>
<pre>[buildout]

extends =
    buildout.cfg
    http://good-py.appspot.com/release/collective.xdv/1.0rc11

eggs +=
    collective.xdv
    number10.demo

develop =
    src/number10.demo</pre>
<p class="callout">The second line of the <i>extends</i> stanza refers to a '<a href="http://good-py.appspot.com/">known good set</a>' of collective.xdv's dependencies. 1.0rc11 is currently the latest version.</p>
<p>Run buildout with our configuration file to get collective.xdv and its dependencies:</p>
<pre>$ ./bin/buildout -c demo.cfg</pre>
<p>Now that all necessary packages are downloaded and ready to go, let's flesh out the number10.demo package. We start by making collective.xdv a dependency so that when we install number10.demo, collective.xdv's configuration is installed too. Edit <i>$HOME/Plone/zinstance/src/number10.demo/number10/demo/profiles/default/metadata.xml</i> as follows:</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;metadata&gt;
  &lt;version&gt;1000&lt;/version&gt;
  &lt;dependencies&gt;
    &lt;dependency&gt;profile-collective.xdv:default&lt;/dependency&gt;
  &lt;/dependencies&gt;
&lt;/metadata&gt;
</pre>
<p>Next, we'll point collective.xdv at our files and configure the domain we want themed. Create <i>$HOME/Plone/zinstance/src/number10.demo/number10/demo/profiles/default/registry.xml</i>:</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;registry&gt;
  &lt;record interface="collective.xdv.interfaces.ITransformSettings"
          field="theme"&gt;
    &lt;value&gt;python://number10.demo/index.html&lt;/value&gt;
  &lt;/record&gt;
  &lt;record interface="collective.xdv.interfaces.ITransformSettings"
          field="rules"&gt;
    &lt;value&gt;python://number10.demo/rules.xml&lt;/value&gt;
  &lt;/record&gt;
  &lt;record interface="collective.xdv.interfaces.ITransformSettings"
          field="domains"&gt;
    &lt;value&gt;
     &lt;element&gt;localhost:8080&lt;/element&gt;
    &lt;/value&gt;
  &lt;/record&gt;
  &lt;record interface="collective.xdv.interfaces.ITransformSettings"
          field="enabled"&gt;
    &lt;value&gt;True&lt;/value&gt;
  &lt;/record&gt;
&lt;/registry&gt;</pre>
<p>That's all the setup done; now we can create the theme and rules files.</p>
<p>First the theme file. We want a page from number10.gov.uk that's fairly typical, not a special case like the homepage. The 'Latest News' page has all the right elements: left hand navigation, breadcrumbs, basic content, etc. Either visit that page in your browser and copy/paste the source into <i>index.html</i>, or download it directly:</p>
<pre>$ wget -O src/number10.demo/number10/demo/index.html http://www.number10.gov.uk/news/latest-news</pre>
<p>Gotta love wget. Now we need to check that CSS resources will load from our local machine. Edit <i>index.html</i> so that all CSS files are referred to by an absolute - not relative - URL, i.e. have an href like <i>http://www.number10.gov.uk/some/path/foo.css</i>, not <i>/some/path/foo.css</i>. Luckily on the Number10 site they're already absolute so there's nothing to do, but I will feel better if line endings are all the same:</p>
<pre>$ dos2unix src/number10.demo/number10/demo/index.html # this step optional</pre>
<p>Better! Next, create a basic rules file at <i>$HOME/Plone/zinstance/src/number10.demo/number10/demo/rules.xml</i>:</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;rules
    xmlns="http://namespaces.plone.org/xdv"&gt;

  &lt;!-- Head: title --&gt;
  &lt;replace theme="/html/head/title" content="/html/head/title" /&gt;

&lt;/rules&gt;</pre>
<p>Only one rule to begin with. That's enough to see that the XDV transform is working.</p>
<h2 id="test-the-transform">Test the transform</h2>
<p>Now let's start Plone, install our number10.demo product and see the XDV transform applied. Start the instance in the foreground:</p>
<pre>$ ./bin/instance fg</pre>
<p>Running Plone like this outputs the log directly in your terminal - useful for spotting problems.</p>
<p>In your browser, go to <i>http://localhost:8080</i> where you'll see that "Plone is up and running". Hit the button to create a new site and log in with the username/password given when you installed (admin/secret in my example). On the subsequent 'Create a Plone site' form just hit the 'Create Plone Site' button. Hello Plone! Click 'admin' in the top right corner, choose 'Site Setup' from the dropdown menu, then on the control panel go to 'Add-ons' under 'Plone Configuration. Install number10.demo (found at the bottom of the available add-ons list).</p>
<p>At this point the XDV theme should kick in. But unfortunately not. The log shows a problem:</p>
<pre>XSLTParseError: Attribute 'onblur': Failed to compile the expression 'this.value = 'Enter search terms';' in the AVT.</pre>
<p>Eek. XDV choked on something nasty. Searching in <i>index.html</i> for 'onblur' we find the culprit: inline JavaScript on an &lt;input&gt; tag. We don't need this, so delete the onfocus and onblur attributes, then refresh the page.</p>
<p>This time success! We have the Number10 theme with the page title coming from Plone</p>
<p style="text-align: center; "><img class="image-inline" src="../images/n10-screenshot2.png/@@images/image/preview" /></p>
<p>Before we continue, now's a good time to populate Plone with some of Number10's content. We configured collective.xdv to theme <i>http://localhost:8080/Plone</i>, but we can still get to the unXDVed theme on <i>http://127.0.0.1:8080/Plone</i>. Point a tab in your browser there, login, and create some folders. For this tutorial I added and published Latest News, Press Briefings and Press Notices inside Plone's usual News folder (allow Folders to be added at <i>http://127.0.0.1:8080/Plone/news/folder_constraintypes_form</i>), which is enough to test breadcrumbs and left hand navigation. For a real demo you'll want at least all the top-level folders.</p>
<h2 id="writing-rules">Writing rules</h2>
<p>Now we're getting into it. The rules file maps Plone's content into the theme file. We'll build up our rules in a couple of stages.</p>
<p><a href="http://pypi.python.org/pypi/xdv/">XDV's PyPI page</a> explains how these rules work far better than I could here. You definitely should read it. Some of these rules are lifted straight from that page.</p>
<p>Update <i>rules.xml</i> to look like this:</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;rules
    xmlns="http://namespaces.plone.org/xdv"
    xmlns:css="http://namespaces.plone.org/xdv+css"&gt;

  &lt;!-- Head: title --&gt;
  &lt;replace theme="/html/head/title" content="/html/head/title" /&gt;

  &lt;!-- Base tag --&gt;
  &lt;append theme="/html/head" content="/html/head/base" /&gt;

  &lt;!-- Body --&gt;
  &lt;prepend theme="/html/body" content="/html/body/attribute::class" /&gt;

  &lt;!-- Top level navigation --&gt;
  &lt;replace css:theme="#top-menu ul" css:content="ul#portal-globalnav" /&gt;

  &lt;!-- Search --&gt;
  &lt;replace css:theme="form#kbs" css:content="form#livesearch0" /&gt;

  &lt;!-- Breadcrumbs --&gt;
  &lt;copy css:theme=".bread_crumb"
        css:content="#portal-breadcrumbs &gt; span:not(:first-child)" /&gt;

  &lt;!-- Page title --&gt;
  &lt;copy css:theme=".pages_textnews_news h2"
        content="//span[@id='breadcrumbs-1']//text()" /&gt;

  &lt;!-- Second level navigation --&gt;
  &lt;copy css:theme=".pages_sidenav_news"
        css:content="#portal-column-one dl.portletNavigationTree ul.navTreeLevel0 &gt; *" /&gt;

  &lt;!-- Footer actions --&gt;
  &lt;replace css:theme="#footer_links ul"
           css:content="#portal-siteactions" /&gt;

&lt;/rules&gt;</pre>
<p>Notice that we use XDV's <code>css</code> namespace to get CSS selectors, which are often much easier to use than XPath. Sometimes XPath is necessary though: for the page title we have to replace the content of an <code>H2</code> tag in the theme with the content of Plone's page title <code>H1</code> tag. XPath can select content where CSS cannot.</p>
<p class="callout">I don't know how I'd write these rules without <a href="http://getfirebug.com/">Firebug</a>. I'm continually switching between XDVed and unXDVed tabs, using Firebug to identify the bits of markup I need. For complex XPath selectors, <a href="https://addons.mozilla.org/en-us/firefox/addon/firefinder-for-firebug/">Firefinder</a> lets you test them directly in the browser.</p>
<p style="text-align: center; "><img class="image-inline" src="../images/n10-screenshot3.png/@@images/image/preview" /></p>
<p>Getting there. Breadcrumbs, page title and left hand nav all look good.</p>
<h2 id="xdv-samurai-sword">xsl:template - XDV's samurai sword</h2>
<p>What's wrong with the primary navigation styles? Inspecting the theme markup we see that each <code>&lt;a&gt;</code> in the top menu has a class named after the menu item.</p>
<pre>&lt;div id="top-menu"&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a class="current_home"&gt;Home&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a class="current_home_news_active"&gt;News&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a class="current_home_communicate"&gt;Transparency&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a class="current_home_meet"&gt;Meet the PM&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a class="current_home_history"&gt;History and Tour&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a class="current_home_nr10tv"&gt;Number 10 TV&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;</pre>
<p>Eugh. Messy. For Number10's existing styles to 'take' we need to reproduce that markup. It's too complex for the usual XDV rules. Time to unsheath the <a href="http://en.wikipedia.org/wiki/Katana">samurai sword</a> that is <code>xsl:template</code>.</p>
<p>As explained on <a href="http://pypi.python.org/pypi/xdv/#inline-xsl-directives">XDV's PyPI page</a> you can include inline XSL in your rules file. These directives apply directly to the markup coming out of Plone. With <code>xsl:template</code> we can match and rewrite arbitrary Plone content.</p>
<pre>&lt;!-- Top level navigation - link class --&gt;
&lt;xsl:template match="//ul[@id='portal-globalnav']//li/a"&gt;
  &lt;xsl:variable name="i"&gt;
    &lt;xsl:value-of select="1 + count(parent::*/preceding-sibling::*)"/&gt;
  &lt;/xsl:variable&gt;
  &lt;xsl:variable name="hardcoded_class"&gt;
    &lt;xsl:choose&gt;
      &lt;xsl:when test="$i = 1"&gt;current_home&lt;/xsl:when&gt;
      &lt;xsl:when test="$i = 2"&gt;current_home_news&lt;/xsl:when&gt;
      &lt;xsl:when test="$i = 3"&gt;current_home_communicate&lt;/xsl:when&gt;
      &lt;xsl:when test="$i = 4"&gt;current_home_meet&lt;/xsl:when&gt;
      &lt;xsl:when test="$i = 5"&gt;current_home_history&lt;/xsl:when&gt;
      &lt;xsl:when test="$i = 6"&gt;current_home_nr10tv&lt;/xsl:when&gt;
      &lt;xsl:otherwise&gt;current_home&lt;/xsl:otherwise&gt;
    &lt;/xsl:choose&gt;
  &lt;/xsl:variable&gt;
  &lt;xsl:variable name="active"&gt;
    &lt;xsl:if test="parent::*[@class='selected']"&gt;_active&lt;/xsl:if&gt;
  &lt;/xsl:variable&gt;
  &lt;xsl:copy&gt;
    &lt;xsl:copy-of select="@*"/&gt;
      &lt;xsl:attribute name="class"&gt;
        &lt;xsl:value-of select="$hardcoded_class"/&gt;&lt;xsl:value-of select="$active" /&gt;
      &lt;/xsl:attribute&gt;
    &lt;xsl:copy-of select="node()"/&gt;
  &lt;/xsl:copy&gt;
&lt;/xsl:template&gt;</pre>
<p>Don't forget to add <code>xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</code> to the <code>&lt;rules&gt;</code> element in your rules file.</p>
<p>What's happening here? Here's a pseudocode version:</p>
<p>For every anchor element in Plone's <code>portal-globalnav</code>:</p>
<ol>
<li>Let <code>i</code> = the current position in the list.</li>
<li>Let <code>hardcoded_class</code> = the appropriate hardcoded class name, dependent on <code>i</code>.</li>
<li>Let <code>active</code> = '_active' if the anchor's parent <code>&lt;li&gt;</code> has the class 'selected'</li>
<li>Add a <i>class</i> attribute to the anchor with the value of <code>hardcoded_class</code> + <code>active</code>.</li>
</ol>
<p>And it works:</p>
<p style="text-align: center; "><img class="image-inline" src="../images/n10-screenshot4.png/@@images/image/preview" /></p>
<p>Why do I call <code>xsl:template</code> a samurai sword? Because <b><code>xsl:template</code> will chop your fingers off!</b> It's incredibly useful but best used very sparingly. The code above is hard to understand - I would not ship it in a production theme. Far better to fix how the CSS is done or - if markup changes are necessary - to override the <code>plone.global_sections</code> navigation viewlet to produce the markup we want.</p>
<p>No doubt that samurai swords are cool. Having discovered you have access to such a weapon, maybe you're tempted to do some serious slicing of Plone's default markup. Here's a sharp tip for you: <b>Don't!</b> Overuse of <code>xsl:template</code> will cripple the maintainability of your site. Rewritten the markup for an Archetypes editing widget in your rules file? If the upgrade from Plone 4.x to Plone 4.y includes a change in the widget's underlying .pt file, you've got a hard-to-catch and hard-to-debug broken form lurking in your site. Tempted to reformat the <code>folder_listing</code> page? You'll likely break the user interface because the JavaScript-generated markup for that page will not pass through your rules.</p>
<p>When in a real theme might you use <code>xsl:template</code> then? When you can write a very generic snippet that applies site wide - something that's easy to read at a glance. For example, by convention Plone's portlets are formatted as an HTML definition list element. Using <code>xsl:template</code> you could neatly change that markup to divs across the whole site.</p>
<p>So you've heeded the ol' great-power-great-responsibility mantra and have resolved to master <code>xsl:template</code> and use it wisely. How do you begin your XSLT training? Personally I found Evan Lenz does a great job of <a href="http://stackoverflow.com/q/1531664/1542734#1542734">demystifying the technology</a>; Evan's <a href="http://oreilly.com/catalog/xsltpr/">O'Reilly book</a> is currently my favourite source of XSLT answers.</p>
<h2>The content column</h2>
<p>Almost there. Now for the main content. Here're the basic rules to add to your <i>rules.xml</i>:</p>
<pre>&lt;!-- Page title --&gt;
&lt;xsl:template match="//h1[contains(concat(' ', normalize-space(@class), ' '),
                     ' documentFirstHeading ')]"&gt;
  &lt;h2 class="page_title_border"&gt;&lt;xsl:copy-of select="./text()"/&gt;&lt;/h2&gt;
&lt;/xsl:template&gt;

&lt;!-- Content --&gt;
&lt;copy css:theme="#inner_container div:first-child"
         css:content="#portal-column-content &gt; *:not(:first-child)" /&gt;
&lt;!-- Drop junk content --&gt;
&lt;drop css:theme="#skip_to_content" /&gt;
&lt;drop css:theme="#rssholder" /&gt;
&lt;drop css:theme="#inner_container div:not(:first-child)" /&gt;
&lt;drop css:theme="#inner_container ~ div.navigation" /&gt;

&lt;!-- Content class --&gt;
&lt;xsl:template match="//div[@id='content']"&gt;
  &lt;div id='content' class='pages_post_news'&gt;
    &lt;xsl:apply-templates /&gt;
  &lt;/div&gt;
&lt;/xsl:template&gt;</pre>
<p class="callout">Note the syntax in the first rule. Matching a class on an HTML element in XPath requires a fairly elaborate construct. You usually cannot do a simple <code>*[@class='foo']</code> because the string must match exactly - that syntax won't match <code>&lt;div class="foo bar"&gt;</code> for example. This works:<br /> <code>*[contains(concat(' ', normalize-space(@class), ' '), ' foo ')]</code><br />Ugly, isn't it? If you need XPath that matches a couple of classes and not another, you quickly end up with a multiline monster of a rule. Laying out the code nicely helps, but I'd love to find a way to define custom XPath selectors in XDV...</p>
<p>The two <code>xsl:template</code> hacks force classes necessary to trigger Number10's existing CSS.</p>
<p style="text-align: center; "><img class="image-inline" src="../images/n10-screenshot5.png/@@images/image/preview" /></p>
<p>Now as a regular user we can navigate around the XDV site and see real pages of content. But as a user with content editing privilege, we get an ugly, unstyled edit bar.</p>
<p style="text-align: center; "><img class="image-inline" src="../images/n10-screenshot6.png/@@images/image/preview" /></p>
<p>The easiest way to get the edit bar looking good is to use just enough of Plone's own CSS.</p>
<p>Plone 4's theme is called Sunburst. Open the main CSS file at <i>$HOME/Plone/buildout-cache/eggs/plonetheme.sunburst-1.0.6-py2.6.egg/plonetheme/sunburst/skins/sunburst_styles/public.css</i>. Create your own CSS file at <i>$HOME/Plone/zinstance/src/number10.demo/number10/demo/demo.css</i> and copy/paste all the lines starting from <code>/* @group Status messages */</code> up to but not including <code>/* @group Control panel */</code>. Add the following at the top of the file:</p>
<pre>/* Hacks */

#edit-bar li {
    display: inline;
}

#inner_container div#edit-bar,
#inner_container div#edit-bar div {
    padding-right: 0;
}

ul#content-views {
    margin: 0;
    padding: 0;
}

#top-menu {
    width: 71%;
}

form#searchGadget_form {
    margin-top: 1px;
}

/* One more from Sunburst: from @group Invisibles */

.hiddenStructure {
    display: block;
    background: transparent;
    background-image: none; /* safari bug */
    border: none;
    height: 0.1em;
    overflow: hidden;
    padding: 0;
    margin: -0.1em 0 0 -0.1em;
    width: 1px;
}
</pre>
<p>We need to do two things to activate this stylesheet. First we register it as a resource. Add to <i>$HOME/Plone/zinstance/src/number10.demo/number10/demo/configure.zcml</i>:</p>
<pre>  &lt;browser:resource
      name="demo.css"
      file="demo.css"
      /&gt;
</pre>
<p>Make sure to add the browser namespace to the <code>&lt;configure&gt;</code> element: <code>xmlns:browser="http://namespaces.zope.org/browser"</code></p>
<p>Stop the instance with <code>Ctrl-c</code> then start it in the foreground again. You can now see your stylesheet in the browser at <i>http://localhost:8080/Plone/++resource++demo.css</i></p>
<p>We need to register that URL with Plone's CSS resource registry. Create a file <i>$HOME/Plone/zinstance/src/number10.demo/number10/demo/profiles/default/cssregistry.xml</i> containing:</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;object name="portal_css"&gt;

 &lt;stylesheet
     id="public.css"
     expression="not: request/HTTP_X_XDV | nothing" /&gt;

 &lt;stylesheet
     id="++resource++demo.css" title=""
     media="screen" rel="stylesheet" rendering="import"
     cacheable="False" compression="safe" cookable="False"
     enabled="1" expression="request/HTTP_X_XDV | nothing"/&gt;

&lt;/object&gt;</pre>
<p>With this file we apply a conditional expression to both our new stylesheet and Sunburst's <i>public.css</i>. We want <i>public.css</i> to render on the unXDVed site, <i>demo.css</i> to render on the XDVed site.</p>
<p>Reinstall number10.demo from the 'Add-ons' control panel (deactivate, then activate again). We also need a new line in <i>rules.xml</i> to pull through Plone's styles. (Note that this brings through styles from other Plone stylesheets like <i>member.css</i>).</p>
<pre>&lt;!-- Pull in Plone CSS --&gt;
&lt;append theme="/html/head" content="/html/head/link | /html/head/style " /&gt;</pre>
<p style="text-align: center; "><img class="image-inline" src="../images/n10-screenshot8.png/@@images/image/preview" /></p>
<p>Ta da! Looking good. Our <i>demo.css</i> introduced the most relevant Sunburst styles, plus some pretty brutal "hacks" to workaround clashes with Number10's existing styles.</p>
<h2 id="up-to-full-site">Moving up to a full site</h2>
<p>So now we have a great-looking, working, demo site. Fingers crossed the client likes what they see and wants you to build their site on Plone. Hoorah! Where to from here?</p>
<ul>
<li>Read the guide to <a href="http://plone.org/products/collective.xdv/documentation/reference-manual/theming">theming with collective.xdv</a> on Plone.org, and the excellent <a href="http://pypi.python.org/pypi/xdv">XDV</a> and <a href="http://pypi.python.org/pypi/collective.xdv">collective.xdv</a> PyPI pages. Everything I've talked about here is documented properly on those pages.</li>
<li><i>client.demo</i> is a throwaway package. Follow the <a href="http://pypi.python.org/pypi/collective.xdv#a-worked-example">collective.xdv worked example</a> to create a proper <i>client.theme</i> package, including a <i>static</i> directory and all your theme's CSS/JavaScript files registered with Plone's resource registries.</li>
<li>Take the opportunity to rework any nasty markup in the theme (looking at you Number10's global navigation). Or if you're writing the theme file fresh, make the CSS sympathetic to Plone's default markup. Though XDV gives you lots of freedom, you'll have less work to do the less you veer from Plone's non-XDV theming approach.</li>
<li>If your theme has a <i><a href="http://meyerweb.com/eric/thoughts/2007/04/18/reset-reasoning/">reset.css</a></i> but you want Plone's <i>public.css</i> styles for content editing, it might help to use <i>cssregistry.xml</i> to control the order as: <i>reset.css</i>, Plone's CSS, <i>overrides.css</i>, your theme's CSS. The <i>overrides.css</i> file goes in your theme package and contains styles to fix up any weirdness. <a href="http://plone.293351.n2.nabble.com/collective-xdv-best-practice-for-theming-the-backend-td5537107.html">Worked for me</a>.</li>
<li>Inspect the source of the Sunburst theme to see how a modern, non-XDV theme is done. That might seem counter-intuitive, but knowing a little about <a href="http://plone.org/documentation/manual/theme-reference">non-XDV Plone theming</a> will allow you to override existing page elements cleanly.</li>
<li>On all but the simplest sites you'll want to add custom dynamic page elements. To start with, learn what Plone's viewlets are and how to register your own.</li>
</ul>
<p>Yes it's true that currently to get the best out of XDV you do need to be somewhat comfortable with the technologies it complements and replaces. The upcoming name change to Diazo shows that the dust hasn't settled yet! For Plone 5, expect Diazo to become the dominant approach and the Plone theming learning curve to mellow out nicely. In the meantime - for just a little effort - XDV can very quickly make your Plone site look great right now.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Dan Jacka</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-04-06T18:15:00Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>





</rdf:RDF>

