<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>VSzA techblog</title>
	<link rel="alternate" type="text/html" href="https://techblog.vsza.hu/"/>
	<link rel="self" type="application/atom+xml" href="https://techblog.vsza.hu/atom.xml"/>
	<updated>2011-07-01T13:04:47+02:00</updated>
   <generator uri="http://github.com/stef/utterson">utterson v0.4</generator>
   <id>https://techblog.vsza.hu/</id>
	<entry>
		<title>Org-mode to RSS and custom HTML</title>
		<link rel="alternate" type="text/html" href="https://techblog.vsza.hu/posts/Org-mode_to_RSS_and_custom_HTML.html"/>
		<updated>2011-07-01T13:04:47+02:00</updated>
      <id>https://techblog.vsza.hu/posts/Org-mode_to_RSS_and_custom_HTML.html</id>
      <author><name>dnet</name></author>
		<category term="POSTCATEGORY" scheme="http://www.sixapart.com/ns/types#category"/>
		<content type="html" xml:lang="en" xml:base="https://techblog.vsza.hu"><![CDATA[
      <p><a href="http://orgmode.org/">Org-mode</a> is one of the many outliner solutions I've seen, and I prefer it because of its slogan "Your Life in Plain Text". It allows me to keep track of my life in form of notes, lists and plans using only a text editor, and as the name suggests, it has its origins in Emacs, and it's possible to export these files to a number of formats. My problem was that I found no easy way to customize the HTML output, and I wanted to create a solution that'd allow me to generate an HTML page and an RSS feed from an .org file of mine.</p>

<p>My first hack was a really rudimentary solution that used ugly regular expressions and sed tied together in a shell script. It had many problems: first of all, it depended heavily on the formatting of the document, even small deviations would've made it fail. Also, it was difficult (e.g. required less-readable constructs) to achieve things that are usually trivial using any XML-friendly environment, for instance closing tags if there are no remaining items, but before closing the whole document.</p>

<pre><code class="bash">#!/bin/bash
INFILE="input.org"
OUTFILE="output.html"
rm -f $OUTFILE
cat &lt;&lt;HTML &gt;$OUTFILE
... HTML header ...
HTML
N=1
while read LINE; do
    OUT=$(echo "$LINE" | sed \
        -e 's/^[^*].*$//' \
        -e 's/^\*\ \(.*\)$/&lt;h2&gt;\1&lt;\/h2&gt;/' \
        -e 's/^\*\*\ DONE\ \[\[\([^]]*\)\]\[\([^]]*\)\]\]/&lt;li class="done"&gt;&lt;a href="\1"&gt;\2&lt;\/a&gt;&lt;\/li&gt;/' \
        -e 's/^\*\*\ \[\[\([^]]*\)\]\[\([^]]*\)\]\]/&lt;li&gt;&lt;a href="\1"&gt;\2&lt;\/a&gt;&lt;\/li&gt;/')
    echo "$OUT" | grep -v '/h2' &gt;/dev/null 2&gt;&amp;1 || [ $N -eq 1 ] || echo "&lt;/ul&gt;" &gt;&gt;$OUTFILE
    N=$[$N + 1]
    echo "$OUT" &gt;&gt;$OUTFILE
    echo "$OUT" | grep -v '/h2' &gt;/dev/null 2&gt;&amp;1 || echo "&lt;ul&gt;" &gt;&gt;$OUTFILE
done &lt;$INFILE
echo "&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;" &gt;&gt;$OUTFILE
</code></pre>

<p>I thought of playing around with third party org-mode parsers, such as the Python one I used and improved called <a href="https://github.com/dnet/dashboard/blob/master/Orgnode.py">Orgnode</a>, but that would've been also a compromise between a clean solution that involves to external org parsing and the simple but rude shell script, having few pros, but the cons of both. In the end I took a look on the export options of org-mode and found that it's capable of creating <a href="http://www.docbook.org/">DocBook</a> output. I hadn't used DocBook before, only heard of it from <a href="http://vmiklos.hu/">vmiklos</a>, but figured out that it's an XML-based document markup language.</p>

<p>The remaining task is transforming XML to XML, and <a href="http://www.w3schools.com/xsl/">XSLT</a> is the most powerful tool for it. I created two stylesheets, one for XHTML output and one for RSS, they almost instantly worked and produced the same (or better) output as the shell script. I also found a bug/feature in the DocBook export as it converts URL quoted special characters to their literal equivalents (such as %C3%B6 to ö), which may cause incompatibilities in some browsers and also makes the RSS invalid.</p>

<pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:db="http://docbook.org/ns/docbook"
  xmlns:xlink="http://www.w3.org/1999/xlink"&gt;
  &lt;xsl:output method="xml" /&gt;
  &lt;xsl:template match="/"&gt;
    &lt;rss version="2.0"&gt;
      &lt;channel&gt;
        &lt;title&gt;...&lt;/title&gt;
        &lt;description&gt;...&lt;/description&gt;
        &lt;link&gt;http://...&lt;/link&gt;
        &lt;lastBuildDate&gt;&lt;xsl:value-of select="$lbd" /&gt;&lt;/lastBuildDate&gt;
        &lt;xsl:for-each select="db:article/db:section/db:section/db:title"&gt;
          &lt;xsl:if test="not(contains(text(), 'DONE'))"&gt;
            &lt;item&gt;
              &lt;link&gt;&lt;xsl:value-of select="db:link/@xlink:href" /&gt;&lt;/link&gt;
              &lt;guid&gt;&lt;xsl:value-of select="db:link/@xlink:href" /&gt;&lt;/guid&gt;
              &lt;description&gt;&lt;xsl:value-of select="db:link" /&gt;&lt;/description&gt;
              &lt;title&gt;&lt;xsl:value-of select="db:link" /&gt;&lt;/title&gt;
            &lt;/item&gt;
          &lt;/xsl:if&gt;
        &lt;/xsl:for-each&gt;
      &lt;/channel&gt;
    &lt;/rss&gt;
  &lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;
</code></pre>

<p>RSS needs the build date to be passed in RFC 2822 format, which is much easier to do in shell rather than some weird XSLT way. I used <a href="http://xmlsoft.org/XSLT/xsltproc2.html">xsltproc</a> which allows parameters to be passed on the command line, and the <em>date</em> command is capable of printing the date just in the right format. This way the RSS can be published using the following command.</p>

<pre><code class="no-highlight">$ xsltproc --stringparam lbd "$(date --rfc-2822)" \
    rss.xsl docbook.xml &gt;feed.rss
</code></pre>
]]></content>
	</entry>
</feed>
