<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Mark Birbeck's Blog]]></title>
  <link href="http://markbirbeck.com//atom.xml" rel="self"/>
  <link href="http://markbirbeck.com//"/>
  <updated>2012-09-14T19:52:15+01:00</updated>
  <id>http://markbirbeck.com//</id>
  <author>
    <name><![CDATA[Mark Birbeck]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Using Knife to launch EC2 instances without a Chef Server]]></title>
    <link href="http://markbirbeck.com//blog/2012/03/16/using-knife-to-launch-ec2-instances-without-a-chef-server/"/>
    <updated>2012-03-16T16:30:00+00:00</updated>
    <id>http://markbirbeck.com//blog/2012/03/16/using-knife-to-launch-ec2-instances-without-a-chef-server</id>
    <content type="html"><![CDATA[<p>In this post we look at how we can make it easy to launch servers on Amazon&#8217;s EC2.
We&#8217;ll use Knife to launch our instances since it gives us a lot of other features
that we can make use of when managing our servers. But we&#8217;ll do this without the
complication of setting up a Chef Server.</p>

<!-- more -->


<h2>Launching instances</h2>

<p>The easiest way to launch a server on EC2 is almost certainly via the control panel.
From there it&#8217;s straightforward to choose an instance size, select a region to
launch into, and so on. However, given that we are always striving to make as much
of our work as possible reproducible then we need a command-line way to launch servers.
The two main options are the Amazon CLI tools and Opscode&#8217;s Knife which is part of the
Chef collection of resources, although for more advanced situations it&#8217;s also
possible to roll your own with libraries like <a href="http://boto.readthedocs.org/en/latest/index.html">Boto</a>.</p>

<h3>The Amazon CLI tools</h3>

<p>The <a href="http://aws.amazon.com/developertools/351">Amazon CLI tools</a> do everything that you need, but are pretty raw. In the
early days of Amazon&#8217;s service there was little else, but now I&#8217;d recommend
using something like Knife.</p>

<h3>Knife</h3>

<p>Knife is part of the <a href="http://wiki.opscode.com/display/chef/Home">Chef suite of tools</a>, and is used for carrying out general
tasks to do with cookbooks and servers. It supports a plug-in architecture and
one of the plug-ins that has been added provides a number of commands for EC2.</p>

<p>Knife and Chef are usually used in conjunction with a Chef server which keeps
track of the servers you&#8217;ve launched, their capabilities, the cookbooks and
recipes you have available, and which of them have been applied to which servers.
However, recently we&#8217;re seeing an increasing number of people using Chef Solo to
get up and running quickly managing Chef cookbooks and recipes by referencing
individual servers directly.</p>

<p>The problem is that whilst we can use the Knife cookbook tools without a Chef
Server, we can&#8217;t use the EC2 commands, so in the instructions that follow we
include a small patch to make this possible.</p>

<p>This small change is a big win, since it gives us a convenient tool for launching
servers and a powerful way to manage our local cookbooks &#8211; all without needing
additional infrastructure. And of course it keeps open the possibility of moving
up to Chef Server in the future.</p>

<h2>Installing Knife</h2>

<p>The quickest way to get up and running with Chef and Knife is by following steps
2 and 3 from Opscode&#8217;s <a href="http://wiki.opscode.com/display/chef/Fast+Start+Guide">Fast Start Guide</a>. And if you&#8217;re using a Mac for
your development (and after all, who isn&#8217;t thinking differently these days?) you
can get up and running even more quickly by simply installing XCode (to get some
Ruby dependencies) and then Chef. Here&#8217;s how:</p>

<h3>Install XCode</h3>

<p>If you have the <em>Mac OS X Install</em> DVD that came with your Mac to hand then open
the <em>Optional Installs</em> folder and then click on <em>XCode</em> to install it (you
can accept the default settings). If you&#8217;ve lost the disk or you just can&#8217;t be
bothered to get out of your chair to find it, then get it from the App Store
(just be prepared for a long download).</p>

<h3>Install Chef</h3>

<p>Once XCode is installed run the following command to install Chef which will also
install Knife. Note that we&#8217;re also asking for the EC2 and GitHub plugins to be
installed as well:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>gem install <span class="se">\</span>
</span><span class='line'>  chef <span class="se">\</span>
</span><span class='line'>  net-ssh net-ssh-multi <span class="se">\</span>
</span><span class='line'>  fog highline <span class="se">\</span>
</span><span class='line'>  knife-ec2 knife-github-cookbooks
</span></code></pre></td></tr></table></div></figure>


<p>There may be a short delay, but after a bit you should get some messages indicating
what has been installed. Once complete, check that all is well by running <code>knife</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>knife --version
</span></code></pre></td></tr></table></div></figure>


<p>You should get back something like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>Chef: 0.10.8
</span></code></pre></td></tr></table></div></figure>


<p>Now that we have the tools we need to add a little bit of configuration information
and patch one of the EC2 sub-commands.</p>

<h3>Configure EC2 security</h3>

<p>If you&#8217;ve already installed the Amazon CLI tools then you will have some of what
you need here, but if you haven&#8217;t then you&#8217;ll need to add your key IDs to your
environment and set a default region. The easiest way to do this is to tack the
values on to the end of your bash profile. You can either edit <code>~/.bash_profile</code>
(still assuming a Mac environment) directly or follow these steps:</p>

<ul>
<li>Add a few variables that will be used in the next command (without the squiggly
brackets):</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">AAKI</span><span class="o">={</span>your access key ID<span class="o">}</span>
</span><span class='line'><span class="nv">ASAK</span><span class="o">={</span>your secret access key<span class="o">}</span>
</span><span class='line'><span class="nv">AZ</span><span class="o">={</span>your preferred availability zone, such as eu-west-1a<span class="o">}</span>
</span><span class='line'><span class="nv">REGION</span><span class="o">={</span>your preferred region, such as eu-west-1<span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>You don&#8217;t <em>have</em> to do this but it makes it just a little bit easier to run the
next command (otherwise you&#8217;ll have to paste each line individually, modifying
the values as you go).</p>

<ul>
<li>Paste the following into a terminal window. It will use the variables we&#8217;ve
just defined to update your profile:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>cat &gt;&gt; ~/.bash_profile <span class="s">&lt;&lt; EOF</span>
</span><span class='line'><span class="s"># Set up Amazon access:</span>
</span><span class='line'><span class="s">#</span>
</span><span class='line'><span class="s">export AWS_ACCESS_KEY_ID=${AAKI}</span>
</span><span class='line'><span class="s">export AWS_SECRET_ACCESS_KEY=${ASAK}</span>
</span><span class='line'><span class="s">export EC2_AVAILABILITY_ZONE=${AZ}</span>
</span><span class='line'><span class="s">export EC2_REGION=${REGION}</span>
</span><span class='line'><span class="s">EOF</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>To get a shell with these new settings applied, either open a new terminal
window, or reload the profile in the current window:</li>
</ul>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nb">source</span> ~/.bash_profile
</span></code></pre></td></tr></table></div></figure>


<h3>Create a Knife configuration file</h3>

<p>The next step is to add a Knife configuration file which will pick up these
default settings. You can paste the following commands into a terminal window:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>mkdir ~/.chef
</span><span class='line'>cat &gt; ~/.chef/knife.rb <span class="s">&lt;&lt; EOF</span>
</span><span class='line'><span class="s"># EC2 sub-command</span>
</span><span class='line'><span class="s">#</span>
</span><span class='line'><span class="s">knife[:availability_zone] = &quot;#{ENV[&#39;EC2_AVAILABILITY_ZONE&#39;]}&quot;</span>
</span><span class='line'><span class="s">knife[:aws_access_key_id] = &quot;#{ENV[&#39;AWS_ACCESS_KEY_ID&#39;]}&quot;</span>
</span><span class='line'><span class="s">knife[:aws_secret_access_key] = &quot;#{ENV[&#39;AWS_SECRET_ACCESS_KEY&#39;]}&quot;</span>
</span><span class='line'><span class="s">knife[:chef_mode] = &quot;solo&quot;</span>
</span><span class='line'><span class="s">knife[:region] = &quot;#{ENV[&#39;EC2_REGION&#39;]}&quot;</span>
</span><span class='line'><span class="s">EOF</span>
</span></code></pre></td></tr></table></div></figure>


<p>Note that we could have placed our keys and regions directly into this file but
there are a number of advantages to the way we&#8217;re doing it here. The first is
that you don&#8217;t need to worry about keeping you <code>knife.rb</code> file secret, which
means you could share it with colleagues if you want to get them set up quickly.
Second, the environment variables that we&#8217;re picking up are also used by other
Amazon-related tools which means (a) if you are using these tools already you
will already have these values set and (b) if you ever change these values you&#8217;ll
only ever need to do it in one place and all of your tools will benefit.</p>

<h3>Modify the Knife EC2 plugin</h3>

<p>The final step is to make a very small change to the EC2 plugin which will make
it easier to use with Chef Solo. The <a href="https://github.com/opscode/knife-ec2">EC2 plugin for Knife is maintained by Opscode</a>
and is designed to be used with Chef Server. This means that once a new server
has been launched on Amazon, Knife will then attempt to register it with Chef
Server and bootstrap it with Chef. We could just ignore the error message that
we get at the end, but since it&#8217;s pretty straightforward to patch and override
plugins, we&#8217;ll do that.</p>

<p>Knife plugins have a nice hierarchical architecture, which means that we can
easily override one of the EC2 sub-commands without having to override all of
them. So first create a directory for your &#8216;personal&#8217; plugins:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>mkdir -p ~/.chef/plugins/knife/
</span></code></pre></td></tr></table></div></figure>


<p>Now get a copy of the patched &#8216;server create&#8217; plugin:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>curl -L https://raw.github.com/gist/2049991/170e0fd2a5b9c5b8532a385d990d04400b182fb4/ec2_server_create.rb <span class="se">\</span>
</span><span class='line'>  &gt; ~/.chef/plugins/knife/ec2_server_create.rb
</span></code></pre></td></tr></table></div></figure>


<p>We should now be all set to launch a server.</p>

<h2>Launching a server</h2>

<p>The command to launch a server in Knife is part of the EC2 plug-in, and looks
something like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>knife ec2 server create <span class="se">\</span>
</span><span class='line'>  --groups<span class="o">=</span>default <span class="se">\</span>
</span><span class='line'>  --region<span class="o">=</span>eu-west-1 --availability-zone<span class="o">=</span>eu-west-1a <span class="se">\</span>
</span><span class='line'>  --image<span class="o">=</span>ami-895069fd --flavor<span class="o">=</span>m1.medium <span class="se">\</span>
</span><span class='line'>  --ssh-user<span class="o">=</span>ubuntu <span class="se">\</span>
</span><span class='line'>  --ssh-key<span class="o">=</span>keyname --identity-file<span class="o">=</span>~/.ssh/keyname.pem
</span></code></pre></td></tr></table></div></figure>


<p>The <code>--groups</code> parameter indicates which security group you want to use. (A
security group is basically a set of firewall settings.) If you want to provide
a list of groups then just use a comma:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>--groups<span class="o">=</span>http,solr,ssh
</span></code></pre></td></tr></table></div></figure>


<p>The <code>--region</code> and <code>--availability-zone</code> parameters determine where your server
will be located and can be omitted if you set them in your environment earlier.</p>

<p>The type of server you want to launch is determined by the <code>--image</code> and <code>--flavor</code>
parameters. There are 32- and 64-bit AMIs, varying by operating system, and in
this example I&#8217;m using a 64-bit version of Ubuntu 11.10 (<code>ami-895069fd</code>). Each
permutation is repeated in each region so you&#8217;ll need to make sure that you get
the right AMI for the region you want to launch the server in. I usually use AMIs
from the <a href="http://uec-images.ubuntu.com/releases/">Ubuntu Cloud Images</a> list.</p>

<p>The <code>--ssh-user</code> parameter determines the user name that will be used to access
the server, and is set in the AMI; if you use AMIs from other sources then you&#8217;ll
need to know the name that was used when creating the image.</p>

<p>Finally, the <code>--ssh-key</code> parameter refers to the name of a key pair that you will
have previously created in Amazon, perhaps via the management console. The
<code>--identity-file</code> parameter refers to the private part of that key pair.</p>

<p>In addition to the keys and region information we can also add <code>image</code> and <code>flavor</code>
to <code>knife.rb</code>. For example:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>cat &gt; ~/.chef/knife.rb <span class="s">&lt;&lt; EOF</span>
</span><span class='line'><span class="s"># EC2 sub-command</span>
</span><span class='line'><span class="s">#</span>
</span><span class='line'><span class="s">knife[:availability_zone] = &quot;#{ENV[&#39;EC2_AVAILABILITY_ZONE&#39;]}&quot;</span>
</span><span class='line'><span class="s">knife[:aws_access_key_id] = &quot;#{ENV[&#39;AWS_ACCESS_KEY_ID&#39;]}&quot;</span>
</span><span class='line'><span class="s">knife[:aws_secret_access_key] = &quot;#{ENV[&#39;AWS_SECRET_ACCESS_KEY&#39;]}&quot;</span>
</span><span class='line'><span class="s">knife[:image] = &quot;ami-895069fd&quot;</span>
</span><span class='line'><span class="s">knife[:flavor] = &quot;m1.medium&quot;</span>
</span><span class='line'><span class="s">knife[:chef_mode] = &quot;solo&quot;</span>
</span><span class='line'><span class="s">knife[:region] = &quot;#{ENV[&#39;EC2_REGION&#39;]}&quot;</span>
</span><span class='line'><span class="s">EOF</span>
</span></code></pre></td></tr></table></div></figure>


<p>This would allow you to launch a new server like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>knife ec2 server create <span class="se">\</span>
</span><span class='line'>  --groups<span class="o">=</span>default <span class="se">\</span>
</span><span class='line'>  --ssh-user<span class="o">=</span>ubuntu <span class="se">\</span>
</span><span class='line'>  --ssh-key<span class="o">=</span>keyname --identity-file<span class="o">=</span>~/.ssh/keyname.pem
</span></code></pre></td></tr></table></div></figure>


<p>Whilst the server is launching you&#8217;ll see a lot of information flying by about
what is going on, including the fact that Knife has bootstrapped Chef for us.
At the end we get a list of details such as the instance ID and the public and
private DNS names and IP addresses, but note that since we&#8217;re using Chef Solo,
Knife has not bootstrapped Chef in the way that it normally would &#8211; but we&#8217;ll
come to that in a follow-up post on using Chef with our instances.</p>

<h2>Managing instances</h2>

<p>You can list and terminate instances with Knife, as well as issue commands to one
or more instances.</p>

<h3>Listing running instances</h3>

<p>To see a list of running instances for a particular region use the <code>server list</code>
sub-command:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>knife ec2 server list --region<span class="o">=</span>eu-west-1
</span></code></pre></td></tr></table></div></figure>


<p>You&#8217;ll get a list of the instances with their public and private IP addresses,
instance IDs, AMI used, and so on.</p>

<h3>Accessing a server</h3>

<p>We can connect to the new server using SSH with the public IP address or DNS name
that was given to us within the output of the Knife <code>server create</code> or <code>server
list</code> commands. The usual <code>ssh</code> command can be used:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>ssh -i ~/.ssh/keyname.pem ubuntu@176.34.221.207
</span></code></pre></td></tr></table></div></figure>


<p>Note that the RSA key and user name must be the same as those used to launch the
server with Knife.</p>

<h3>Terminating a running instance</h3>

<p>You can shutdown a server with its instance ID which you can get from the <code>server
list</code> command. For example:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>knife ec2 server delete i-a4ddeced --region<span class="o">=</span>eu-west-1
</span></code></pre></td></tr></table></div></figure>


<p>You&#8217;ll be asked to confirm that you really want to shutdown the server, although
you can add a <code>-y</code> option if you&#8217;re feeling confident. If you run the list
command again you&#8217;ll see that the <code>State</code> column says <code>shutting-down</code>.</p>

<h2>Conclusion</h2>

<p>That&#8217;s it &#8211; you now have a way to quickly launch and terminate servers in the
cloud which is a bit easier than the usual Amazon command-line tools. What&#8217;s more,
the tool we use to start and stop instances gets us onto the Chef ladder for
easy deployment and configuration. We&#8217;ll look at how we can use Chef on our
instances in a future post.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Choosing a Blogging Platform]]></title>
    <link href="http://markbirbeck.com//blog/2012/02/24/choosing-a-blogging-platform/"/>
    <updated>2012-02-24T17:17:00+00:00</updated>
    <id>http://markbirbeck.com//blog/2012/02/24/choosing-a-blogging-platform</id>
    <content type="html"><![CDATA[<p>The great thing about not having blogged for a few years is that I&#8217;ve just had
the opportunity to survey the blogging landscape. If you&#8217;re drinking <em>lean start-up</em>
kool aid or you&#8217;re a technical blogger, then what I learned may be useful to you.</p>

<!-- more -->


<h2>The Cloud for Everything</h2>

<p>The two blogging platforms I used in the past were Blogger (for my posts about
XForms and internet applications) and Drupal (for my company posts). The first
thing I knew for certain was that I didn&#8217;t want to
manage my blog infrastructure. After too many holidays interrupted by trying to
resolve problems, I spent a number of years putting anything that I could into the cloud.</p>

<p>The initial part of the journey to the cloud involved replacing services that
we were already running on our own servers with those provided by others. For
example:</p>

<ul>
<li>email, calendar, contacts and documents were moved to Google Apps;</li>
<li>everyday files were placed in Dropbox and Sugar Sync and more system-related material
into S3 (usually thanks to the excellent <a href="http://cyberduck.ch/">Cyberduck</a>);</li>
<li>SVN and Trac servers were shutdown in favour of Bitbucket, which later gave way to
Google Code and then Github;</li>
<li>Bugzilla was dropped in favour of LightHouse;</li>
<li>SugarCRM servers were switched off in favour of Salesforce;</li>
<li>and mail servers were dropped for Mailchimp.</li>
</ul>


<p>Then, with lots of servers doing nothing I stopped our contract with WebFusion
and shipped the servers back to the office&#8230;where of course they then gathered dust
because everything was now being moved to RightScale+EC2, Google App Engine and
Heroku. Soon the only server left in the office
was a flakey DNS box and even that was eventually shut down in favour of DNS Made Easy, and
then Route 53.</p>

<p>In short, if there was anything that someone else could manage better than us we let them,
until our office ended up with a single computer per person and a wi-fi router. Now the
only services we managed were web-sites for our customers and ourselves, and these were
on servers running at Amazon.</p>

<p>But when I say &#8216;except for our own web-site&#8217; that hides a lot. Since we were building
web-sites for other companies (albeit with a lot of back-end functionality) it seemed
that we really ought to be managing our own. Even though the site was
actually just a collection of blog-posts and an enquiry form, it still felt wrong
to use something like Blogger or WordPress to convey our ideas and plans to the world,
so we continued with Drupal.</p>

<h2>Drupal</h2>

<p>In retrospect it&#8217;s interesting that my blogs hung on for so long without being &#8216;outsourced&#8217;.
Perhaps it&#8217;s because
Drupal does quite a nice job of serving up good blogs by way of its plethora of modules &#8211;
it really is very easy to add tags, comments, avatars, images, OAuth and RSS feeds, and
it&#8217;s also a snap to ensure that your latest pearls of wisdom from Twitter and Facebook
appear on your site.</p>

<p>But it&#8217;s not just how powerful Drupal is; the quality of blogging platforms two years ago
really wasn&#8217;t a patch on what it is today, and that is probably one of the key things
that has changed. When you look now at the state-of-the-art with
Blogger, Posterous, WordPress and Tumblr, you really have to come up with some pretty
solid reasons as to why you would maintain your own database and web front-end.</p>

<h2>Blogger</h2>

<p>So I&#8217;ve obviously convinced myself to drop Drupal and the whole self-hosting
approach, but what should I replace it with?</p>

<p>My other blog faired reasonably well on Blogger over the years, so that platform was obviously
a candidate. Google have recently revamped the look-and-feel, and it&#8217;s also easy to import and
export information, create new posts from a variety of places, and use external
JavaScript components such as <a href="http://disqus.com/">Disqus</a>. All of these things make Blogger
a strong candidate but in the end the amount of Google branding they add to your blog,
coupled with the lack of support for Markdown (more on this below) meant that I
decided against it.</p>

<p>However, it&#8217;s worth stressing that Blogger&#8217;s ability to easily import and export
your posts, as well as its support for Disqus (which means that you can take with
you the comments people leave on your blog, should you move platforms), meant I really
had to think hard about it. I believe that structuring your use of services in
such a way that you can move your data around whenever you want to should be an
important part of the lean mindset, and Blogger really helps that.</p>

<h2>Posterous</h2>

<p>Right from the start I really liked the feel of Posterous. Highlights for me are that
you can create public and private spaces and add new posts from just about anywhere.
But before long I hit problems.</p>

<p>The first issue came when I tried to import data from my old blogs. Posterous
can&#8217;t import from Drupal but since it can read from Blogger I tried to use that
as an intermediary to get from Drupal to Posterous. Unfortunately it failed, and
even after some very prompt and friendly help from Posterous support it still couldn&#8217;t be made to work.</p>

<p>It shows how much I liked Posterous though that at one point I considered abandoning
my old posts in favour of cherry-picking a few&#8230;until that is, I
discovered that it was not possible to use Disqus. That was a
show-stopper because one of the most important aspects of my new blog is that I should
depend as little as possible on any particular platform, and having both posts
<em>and</em> comments embedded in the platform seemed too risky.</p>

<h2>Tumblr</h2>

<p>Tumblr was initially lower down my list than Posterous because of the way that it
presents itself as an activity stream and a community, rather than a blog &#8211; I liked it,
but it felt like I was going against the flow to use it as a place to write technical
articles. But after
a little playing around I actually started to like it more than Posterous, and with
a few tweaks the longer technical posts could be made to look less out of place.</p>

<p>Tumblr has no problem with Disqus, and as I started to play with it more I
discovered more and more references to it in the settings panels of other services that I used,
such as Meetup.</p>

<p>But in the end it was ironically Tumblr&#8217;s biggest advantage for me that led to my <em>not</em>
using Tumblr.</p>

<h2>Markdown</h2>

<p>If your blog mainly includes articles that contain code snippets
and embedded screenshots then writing directly in HTML is laborious. Using any of
the inline editors that blogging platforms invariably provide doesn&#8217;t really help
either since it involves way too many mouse-clicks (and often the HTML that is
generated is a mess). So in this area Tumblr&#8217;s biggest plus &#8211; at least for me &#8211;
is that it supports the use of <a href="http://daringfireball.net/projects/markdown/">Markdown</a> to enter articles.</p>

<p>But once I started thinking about my preference for Markdown, and started to think
about the kinds of blog-posts I wrote, I realised that being able to control how
code snippets and screenshots appear was pretty much the <em>most important</em> thing
that I needed. And the best tool I&#8217;d found for that was <a href="http://jekyllrb.com/">Jekyll</a>, the static site
generator.</p>

<h2>Static Site Generation</h2>

<p>Whilst spending time with Tumblr and Posterous I was also toying with the idea
of using a static site generator. If you&#8217;re not familiar with it, the idea is
simply to generate a set of static HTML pages from your posts, and then to deploy
those pages to a simple web server. Since they are static the pages are delivered
very quickly, with little to go wrong. And because they are static, deployment
can be as simple as using GitHub Pages or an S3 folder.</p>

<p>Each time I have considered the idea in the past I have rejected it, primarily
because the publishing process generally requires you to be able to have access to your
development machine. But then you
start to wonder whether you would actually ever use any of the additional methods
that Blogger, Tumblr and Posterous support
for getting your posts online; would
I really blog from my phone whilst out with the kids in the park, or during a meal at
a restaurant with friends? And if I did, would I send that post to the same blog that I
use for discussing test-driven development and big data? It was starting to dawn on
me that with all the other benefits that I would get from having a static site,
I could live with only being able to deploy from my main work computer.</p>

<h3>Jekyll v. Hyde</h3>

<p>Of course given the tortuous tour I&#8217;d had through the world of blogging platforms, it was
a certaintly that choosing a site generator was not going to be easy either.
Jekyll is great, but it&#8217;s written in Ruby and I now do everything in Python.
I&#8217;ve done a little Ruby in the course of constructing Chef scripts but I prefer to
focus on as few languages as I can, so the search was on for a Python equivalent
to Jekyll, which is how I came across <a href="http://hyde.github.com/">Hyde</a>.</p>

<h3>Octopress</h3>

<p>However, at the same time that I found Hyde I also came across <a href="http://octopress.org/">Octopress</a>, a framework
that sits around Jekyll sporting a nice theme and many interesting plug-ins. With
Octopress it&#8217;s not only possible to insert code snippets with language-specific
formatting, but it&#8217;s also possible to insert files from your local drive, snippets from gist,
excerpts from other posts, and so on. In other words, when it comes to creating a blog about
coding, Octporess makes it very easy to manage all the material you need, and to present it
nicely.</p>

<p>Hyde is great too, but more effort has been put into making the framework easy
to extend, whilst Octopress has seen a lot more effort directed at giving the resulting
site a great, clean, look. Of course, if I ever wanted to add my own plug-ins I&#8217;d
prefer to be with Hyde, but for now I&#8217;m going to treat Octopress as a standalone
tool that produces nice looking technical sites, and ignore the Python/Ruby issue.</p>

<p>My suspicion is that I haven&#8217;t finished with blogging platforms just yet, but with
my posts stored as Markdown and any comments to the site stored in Disqus &#8211; not
to mention other assets such as images and presentations stored in
Flickr, Skitch, S3, YouTube, SlideShare, <em>et. al.</em> &#8211; I think I&#8217;m travelling about
as light as I can and should be able to switch pretty easily if something else
looks better.</p>

<h2>Conclusion</h2>

<p>As services become increasingly specialised it doesn&#8217;t make sense to manage your
own &#8211; far better to spend time in the areas where you can add value. Modern
blogging platforms make it very easy to create a site that is as good
as anything you could create on your own managed platform.</p>

<p>However, it&#8217;s still
important to think about how easy it would be to shift platforms should the need
arise, and for this reason it&#8217;s important to place resources like comments, images and videos outside
the blogging platform.</p>

<p>And if your blog is development-oriented then most of these online services won&#8217;t
really offer the same control over the output of your site as a static site generator
like Jekyll coupled with Octopress does.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Dog bites man in race to Semantic Web]]></title>
    <link href="http://markbirbeck.com//blog/2010/08/05/dog-bites-man-in-race-to-semantic-web/"/>
    <updated>2010-08-05T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2010/08/05/dog-bites-man-in-race-to-semantic-web</id>
    <content type="html"><![CDATA[<p>Facebook&#8217;s adoption of RDFa as a way to provide extra features to its users has
met with an ecstatic welcome by some, and suspicion and criticism by others.
Here we discuss whether some in the semantic web community may be being too
hard on their efforts.</p>

<!-- more -->


<p>Ten years ago, did you expect there ever to be a semantic web?</p>

<p>How you answer that question will depend a lot on what you&#8217;ve been doing during
that decade. If you don&#8217;t know what RDF or DARPA are, then my guess is that ten
years ago you&#8217;d have been in the &#8216;Tim Berners-Lee is a dreamer&#8217; camp.</p>

<p>If you <em>did</em> know about RDF back then, you&#8217;d have rather quaintly been saying
that all we need to do to get semantic web lift-off, is to persuade people to
code their data up using RDF/XML. (As if people didn&#8217;t have lives to lead, or
something.)</p>

<p>Fast forward to today, and ask the same question.</p>

<p>My guess is that today, many more people will answer that question positively,
and agree that the semantic web is a viable proposition &#8211; perhaps even about
to happen in the way that its visionaries had always hoped it would.</p>

<p>Of course, we didn&#8217;t get here in a smooth way, because that would imply that
we knew all the answers in advance. We got where we are today &#8211; and by &#8216;we&#8217;
I mean us, humans&#8230;everyone &#8211; by trying things that almost worked but didn&#8217;t
quite, by meeting people from different disciplines and swapping ideas, by
speaking, writing articles, creating code, doing PhDs in triple-store
performance and inference, and generally experimenting. And we did all of
these things (and more) because we knew instinctively that we could create a
web that was even more powerful than the fantastical beast we already had.</p>

<p>As you&#8217;d expect, sometimes, some of us did the right thing for the wrong
reasons. But that&#8217;s ok, because unless you think that there is something or
someone out there keeping score, then ultimately, whatever the motivation, it
all helps.</p>

<h3>Facebook</h3>

<p>So when I read Alex Iskold on how Facebook&#8217;s goal &#8220;is not to create a better,
more structured Web&#8221; (<a href="http://www.readwriteweb.com/archives/does_facebook_really_want_a_semantic_web.php">Does Facebook Really Want a Semantic Web?</a>), I
couldn&#8217;t help but wonder what the story is. Actually, more than that, I&#8217;m
asking myself exactly how do some of the very clever people who have contributed
stirling work to the semantic web actually think that the <em>real</em> semantic web
(the one that everyone will use) is going to come about &#8211; other than in a
messy, weaving, &#8216;one step forwards, two steps back&#8217; kind of a way. (See also
Ian Davis&#8217; <a href="http://blog.iandavis.com/2009/05/googles-rdfa-a-damp-squib">Google&#8217;s RDFa a Damp Squib</a> for the same take, almost exactly
a year ago.)</p>

<p>This structured web is just a tool, a means to many ends. So it will <em>always</em>
be the case that anyone who uses it will be doing so for their own reasons, and
<em>not</em> &#8220;to create a better, more structured Web&#8221;. Selling products, marking up
election results, identifying genomes, categorising research papers &#8211; rarely
will these things be done with the primary goal of a &#8220;more structured web&#8221;, for
its own sake, and we should be grateful for that.</p>

<h3>The web was already messy</h3>

<p>But purity of motivation aside, I think there are other problems with Alex&#8217;s
article &#8211; if we&#8217;re going to tilt at windmills, we might want to establish
who owns them first. For example, is it really Facebook&#8217;s fault that a &#8220;growing
amount of user profile data is full of duplicates and ambiguity&#8221;, as Alex says?
Can we really blame them that the &#8220;[a]bsence of semantics creates fragmented
connections and noise around the Web&#8221;?</p>

<p>Don&#8217;t get me wrong, the people who know how to do the right thing should
continue to do the right thing, and they should also be on hand to persuade
the Facebooks of this world to do the right thing, too. (And the Googles and
the Yahoo!s aswell, because they didn&#8217;t get it right first time, either.) But
the semantic web community also needs to take a hard look at what it is asking
people to do, and constantly look for opportunities to simplify its standards.</p>

<h3>Out of the shadows</h3>

<p>When Alex says that Facebook&#8217;s proposals were &#8220;targeted more towards PR than
correctness&#8221; I have flashbacks to ten years ago when the mere mention of RDF
would invoke derision (literally). I wonder what we would have thought back
then, if someone had told us that some enormous companies with millions of
users would be adopting semantic technologies, and trying to get good PR for
it. We&#8217;d no doubt have dismissed that as a &#8220;man bites dog&#8221;, story.</p>

<p>Whatever their motivations, and regardless of whether they got it perfectly
right or just pretty close, Facebook really are actively contributing to a
&#8220;better, more structured Web&#8221;.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Issue-driven development with Mercurial patch queues and Google Code]]></title>
    <link href="http://markbirbeck.com//blog/2010/04/24/issue-driven-development-with-mercurial-patch-queues-and-google-code/"/>
    <updated>2010-04-24T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2010/04/24/issue-driven-development-with-mercurial-patch-queues-and-google-code</id>
    <content type="html"><![CDATA[<p><em>Note that since this post was written I&#8217;ve moved to Git and GitHub. However,
I still use the same workflow.</em></p>

<p>One of the things I like best about using Mercurial patch queues is the way
that you can continually refine the commit message before you send anything
back to your repository. Since the message won&#8217;t actually appear in your
revision history until you convert the patch to a proper commit, you can hone
the message as you work. This becomes particularly powerful when combined with
Google Code&#8217;s ability to update issues based on your commit messages, and
greatly assists with <em>issue-driven development</em>.</p>

<!-- more -->


<p>Let&#8217;s use a real scenario to illustrate.</p>

<p>I wanted to improve the performance of toggling the XForms <code>case</code> element, in
the XForms part of <a href="http://backplanejs.googlecode.com/">backplanejs</a>. Given that I generally use an IDD approach,
the first thing I did was to create an issue (<a href="http://code.google.com/p/backplanejs/issues/detail?id=45">issue 45: &#8220;Improve performance of case toggling&#8221;</a>).</p>

<p>Over in Mercurial I then created a new patch. I gave it the name &#8216;issue-45&#8217; and
asked Mercurial to let me edit the commit message:</p>

<pre><code>hg qnew issue-45 -e
</code></pre>

<p>My assigned editor opened and I entered the following:</p>

<pre><code>Improve performance of case toggling.

Fixes issue 45.
</code></pre>

<p>I tend to keep the first line of these commit messages fairly short, because it
is used by Mercurial in various places, such as when you list your current
patches with <code>hg qseries</code>. But after that you can put whatever you like.</p>

<p>The &#8220;Fixes issue 45.&#8221; part is the interesting bit. When Google Code sees this
message it will close issue 45 and automatically provide a link to the changeset
in the issue&#8217;s comments. This message will then be added to the changeset, and
the reference to &#8216;issue 45&#8217; will become a link to the issue. (You can also add
comments without closing the issue, generate a new issue, add labels, and so on.
See <a href="http://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control">issue-tracker help</a> for more information.)</p>

<p>None of these changes happen until we commit our code to the Google Code
repository, which means we can work on our changes and the associated
commit message until we&#8217;re happy.</p>

<p>As I worked on improving performance, it became clear that when we toggle the
state of a form control from enabled to disabled, we should be a bit more
efficient about how we manage changes to the CSS classes. The normal operation
is to set the CSS to &#8216;enabled&#8217; or &#8216;disabled&#8217;, but the code was first calling
code to remove <em>both</em> values, before then writing back whichever value
represented the current state of the control.</p>

<p>Since there were actually two improvements I could make I raised issues 46 and
47, with appropriate explanations. When I&#8217;d finished updating the code I did
the usual &#8216;refresh&#8217; to put the code in the patch, but I also told Mercurial
that I wanted to update the commit message:</p>

<pre><code>hg qrefresh -e
</code></pre>

<p>My editor opened and I was able to change the message to this:</p>

<pre><code>Improve performance of case toggling.

Fixes issue 45.
Fixes issue 46.
Fixes issue 47.
</code></pre>

<p>After making the required changes, all that remained was to convert my patch
into a proper commit in my repository:</p>

<pre><code>hg qfinish -a
</code></pre>

<p>Of course Google Code still hasn&#8217;t seen these messages, and that requires a
&#8216;push&#8217;:</p>

<pre><code>hg push
</code></pre>

<p>This final action automatically closes all three issues for me, and adds
cross-referencing messages to both the changeset and the issues.</p>

<p>You can see the result by looking at <a href="http://code.google.com/p/backplanejs/issues/detail?id=45">issue 45</a> or <a href="http://code.google.com/p/backplanejs/source/detail?r=d6ea4e794d">revision d6ea4e794d</a>.
When used with the diff feature when looking at a changeset, this gives a
detailed record of the changes that were made, and why &#8211; ideal for IDD.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Vocabularies, token bundles and profiles in RDFa]]></title>
    <link href="http://markbirbeck.com//blog/2010/02/25/vocabularies-token-bundles-and-profiles-in-rdfa/"/>
    <updated>2010-02-25T00:00:00+00:00</updated>
    <id>http://markbirbeck.com//blog/2010/02/25/vocabularies-token-bundles-and-profiles-in-rdfa</id>
    <content type="html"><![CDATA[<p>A number of discussions are taking place in the new <a href="http://www.w3.org/2010/02/rdfa/">W3C RDFa Working Group</a>
about how to enable authors to use tokens in place of URIs. How do we avoid
conflicts if anyone can define their own tokens? This post looks at how this
might be achieved.</p>

<!-- more -->


<p>(The following discussion continues some of the themes from last year&#8217;s post
<a href="http://markbirbeck.com//blog/2009/04/30/tokenising-the-semantic-web">Tokenising the Semantic Web</a>.)</p>

<h3>A contract between consumer and publisher</h3>

<p>The first thing to say is that what we are talking about is allowing publishers
to establish a contract with the page consumer.</p>

<p>Looking at the vocabulary problem this way frees us from having to assume that
some document will be downloaded to find out how to process everything &#8211; the
so-called <em>follow your nose</em> issue which I&#8217;ll come back to.</p>

<p>Instead, at the most fundamental level we simply want to allow Google (for example)
to be able to say to authors, &#8220;if you use some previously agreed upon &#8216;switch&#8217; in
your documents, then we&#8217;ll interpret your RDFa in some agreed upon way&#8221;.</p>

<p>I begin with this because it establishes that we are looking for two things:
primarily a way to identify a set of tokens (i.e., a way to provide that &#8216;switch&#8217;),
and only secondarily are we looking for a way to set up retrievable tokens. I&#8217;m
emphasising this because I feel in previous discussions there has been a tendency
to look <em>only</em> for a solution to the second issue &#8211; i.e., the &#8216;follow-your-nose&#8217;
solution &#8211; and this has the tendency to prematurely eliminate simpler solutions
form consideration.</p>

<h3><code>@profile</code></h3>

<p>I&#8217;ve always favoured using the <a href="http://www.w3.org/TR/html401/struct/global.html#profiles">HTML 4.01 profile attribute</a> for this contract,
since it already exists, and its meaning in HTML 4.01 is very similar to what we
need.</p>

<p>In particular, the HTML 4.01 spec says:</p>

<blockquote><p>User agents may use this URI in two ways:</p>

<ul>
<li><p>As a globally unique name. [&#8230;]</p></li>
<li><p>As a link. [&#8230;]</p></li>
</ul>
</blockquote>

<p>This is ideal, since it says that we <em>may</em> do FYN, but we also might simply &#8216;know&#8217;
intrinsically what to do. In other words, it gives us the opportunity to do both,
which is crucial as we&#8217;ll see.</p>

<p>So what would a Google example look like, if we used <code>@profile</code> as the &#8216;switch&#8217;?</p>

<p>Taking an example from the <a href="http://www.google.com/support/webmasters/bin/answer.py?answer=146646">Rich Snippets tutorial</a>, it might look like this
(note that the original sample uses <code>@property="url"</code>, rather than <code>@rel</code> so I&#8217;ve
retained that here):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">typeof=</span><span class="s">&quot;Person&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;name&quot;</span><span class="nt">&gt;</span>John Smith<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;nickname&quot;</span><span class="nt">&gt;</span>Smithy<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;url&quot;</span><span class="nt">&gt;</span>http://www.example.com<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;affiliation&quot;</span><span class="nt">&gt;</span>ACME<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">rel=</span><span class="s">&quot;address&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>        <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;locality&quot;</span><span class="nt">&gt;</span>Albuquerque<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;title&quot;</span><span class="nt">&gt;</span>Engineer<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;http://darryl-blog.example.com/&quot;</span> <span class="na">rel=</span><span class="s">&quot;friend&quot;</span><span class="nt">&gt;</span>Darryl<span class="nt">&lt;/a&gt;</span>
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Note that all I&#8217;ve done is to:</p>

<ol>
<li>make up a URI for a profile; of course the actual URI is up to Google, not me,
but as you can see, for the sake of discussion, I&#8217;m pretending that there are
different versions of a profile, and so I&#8217;ve built my imaginary URI accordingly;</li>
<li>remove the namespace prefixes from the terms in @property and @rel. Of course
a profile could do all sorts of mappings to get back to the desired URIs.</li>
</ol>


<p>Now, when Google retrieve a document that has this profile defined, they can assume
the contract I mentioned &#8211; they can assume that the publisher is writing this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>@typeof=&quot;Person&quot;
</span></code></pre></td></tr></table></div></figure>


<p>as a shorthand for this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>@typeof=&quot;http://rdf.data-vocabulary.org/#Person&quot;
</span></code></pre></td></tr></table></div></figure>


<h4>Omitting <code>@profile</code></h4>

<p>It&#8217;s often asked in these discussions, &#8216;but what if the author doesn&#8217;t include the
profile attribute&#8230;aren&#8217;t we left with unusable tokens?&#8217; It&#8217;s a fair question,
because after all the tokens now really don&#8217;t mean anything.</p>

<p>But from an RDFa standpoint it is no different to the situation when authors omit
namespace declarations. Here&#8217;s the original rich snippets example, but without
the <code>v</code> prefix declaration:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">typeof=</span><span class="s">&quot;v:Person&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;v:name&quot;</span><span class="nt">&gt;</span>John Smith<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;v:nickname&quot;</span><span class="nt">&gt;</span>Smithy<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;v:url&quot;</span><span class="nt">&gt;</span>http://www.example.com<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;v:affiliation&quot;</span><span class="nt">&gt;</span>ACME<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">rel=</span><span class="s">&quot;v:address&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>        <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;v:locality&quot;</span><span class="nt">&gt;</span>Albuquerque<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;v:title&quot;</span><span class="nt">&gt;</span>Engineer<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;http://darryl-blog.example.com/&quot;</span> <span class="na">rel=</span><span class="s">&quot;friend&quot;</span><span class="nt">&gt;</span>Darryl<span class="nt">&lt;/a&gt;</span>
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>As you can see, it&#8217;s no more meaningful than our &#8216;missing profile&#8217; example.</p>

<h4>Mixing profiles</h4>

<p>So, we&#8217;ve established that <code>@profile</code> can be used as a &#8216;switch&#8217; to enable a
whole set of tokens, and all that an organisation needs to do is to explain
clearly what mapping will take place between tokens and URIs, when that switch
is used; as long as authors know how their data is going to be interpreted,
then organisations like Google and Yahoo! can simply publish a profile URI and
indicate what it means.</p>

<p>But what if our document-publisher adds another profile to their document?
<code>@profile</code> is defined in HTML 4.01 to be a space-separated list of values,
so this is already legitimate, but what should happen when we get this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;body</span>
</span><span class='line'> <span class="na">xmlns:Person=</span><span class="s">&quot;http://rdf.data-vocabulary.org/#Person&quot;</span>
</span><span class='line'> <span class="na">xmlns:name=</span><span class="s">&quot;http://rdf.data-vocabulary.org/#name&quot;</span>
</span><span class='line'> <span class="err">.</span>
</span><span class='line'> <span class="err">.</span>
</span><span class='line'> <span class="err">.</span>
</span><span class='line'><span class="nt">&gt;</span>
</span><span class='line'>    <span class="c">&lt;!-- Some documentation about the profile here, to make it human readable. --&gt;</span>
</span><span class='line'><span class="nt">&lt;/body&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Making a profile into an HTML document gives us the possibility of profiles loading
other profiles. For example, recall that I pretended that the 2010 version of this
profile included the CC profile; this &#8216;import&#8217; might be achieved as easily as this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;body</span>
</span><span class='line'> <span class="na">xmlns:Person=</span><span class="s">&quot;http://rdf.data-vocabulary.org/#Person&quot;</span>
</span><span class='line'> <span class="na">xmlns:name=</span><span class="s">&quot;http://rdf.data-vocabulary.org/#name&quot;</span>
</span><span class='line'> <span class="err">.</span>
</span><span class='line'> <span class="err">.</span>
</span><span class='line'> <span class="err">.</span>
</span></code></pre></td></tr></table></div></figure>


<p>If profiles could import other profiles, it would also make versioning incredibly easy.
For example, if our fictitious 2010 profile were to enhance the 2009 version by adding
both the CC profile and a new predicate called &#8216;foo&#8217;, we could simply declare the 2010
profile as including the 2009 profile, rather than expressing all of the tokens again:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;body</span>
</span><span class='line'> <span class="na">xmlns:foo=</span><span class="s">&quot;http://rdf.data-vocabulary.org/#foo&quot;</span>
</span><span class='line'><span class="nt">&gt;</span>
</span><span class='line'>    <span class="c">&lt;!-- Some documentation about the profile here, to make it human readable. --&gt;</span>
</span><span class='line'><span class="nt">&lt;/body&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<h4>JSON profiles</h4>

<p>For various reasons I think the basic level of conformance for expressing token bundles
should be to use JSON. Given that we are only concerned with name/value pairs, then all
we need is this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="s2">&quot;Person&quot;</span><span class="o">:</span> <span class="s2">&quot;http://rdf.data-vocabulary.org/#Person&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;http://rdf.data-vocabulary.org/#name&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="p">.</span>
</span><span class='line'>    <span class="p">.</span>
</span><span class='line'>    <span class="p">.</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>However, since the most common application of this will be to retrieve tokens in browsers,
we should really use <a href="http://en.wikipedia.org/wiki/JSON#JSONP">JSONP</a> so that the browser gets a chance to retrieve the data.
Something like this would do it:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nb">document</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">addMappings</span><span class="p">({</span>
</span><span class='line'>    <span class="s2">&quot;Person&quot;</span><span class="o">:</span> <span class="s2">&quot;http://rdf.data-vocabulary.org/#Person&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;http://rdf.data-vocabulary.org/#name&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="p">.</span>
</span><span class='line'>    <span class="p">.</span>
</span><span class='line'>    <span class="p">.</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>This could easily be achieved by our theoretical parser calling out to a theoretical
server with the following URL:</p>

<pre><code>http://rdf.data-vocabulary.org/profile/2010.json?jsonp=document.meta.addMappings
</code></pre>

<h3>Handling conflicts</h3>

<p>If a generic parser is able to load token bundles from all quarters, then we now have
a situation where the short-form tokens that authors are able to use can be ambiguous.</p>

<p>There are two issues here, one is to decide what should happen in a conflict situation,
and the other is how to let authors know.</p>

<h4>Last wins</h4>

<p>The first issue &#8211; what should happen when a conflict occurs &#8211; <em>could</em> be resolved by
saying that duplicate tokens are an error, but I think it&#8217;s obvious that this is the
worst approach we could take. To avoid errors we&#8217;d need to establish central registries,
and then we&#8217;d have immediately flipped from a decentralised solution to a centralised one.</p>

<p>It would be better to say that tokens are loaded in the order in which they appear in the
document, and newer tokens simply override older ones.</p>

<p>Not only is this clear, but it would also allow for scenarios such as one organisation
creating a profile that makes a small number of modifications to someone else&#8217;s profile,
by overriding certain tokens. And it would also allow minor changes to be made to a
profile without having to issue a whole new profile:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">typeof=</span><span class="s">&quot;Person&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;http://rdf.data-vocabulary.org/#name&quot;</span><span class="nt">&gt;</span>John Smith<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;nickname&quot;</span><span class="nt">&gt;</span>Smithy<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    .
</span><span class='line'>    .
</span><span class='line'>    .
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>The author could of course reverse the order of the <code>@profile</code> URIs, but this might start
getting a little difficult to keep track of whilst editing.</p>

<p>A better solution is to make use of &#8216;@profile everywhere&#8217;, and to scope the token bundle.
An author can then place their <code>@profile</code> declaration closer to the mark-up that it relates
to. In the following example we have the FOAF profile as our default throughout the document,
but when we insert a Google-specific notion of a <code>Person</code> we also put the profile identifier
on the root element:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">typeof=</span><span class="s">&quot;Person&quot;</span> <span class="na">profile=</span><span class="s">&quot;http://rdf.data-vocabulary.org/profile/2009&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;name&quot;</span><span class="nt">&gt;</span>John Smith<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;nickname&quot;</span><span class="nt">&gt;</span>Smithy<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    .
</span><span class='line'>    .
</span><span class='line'>    .
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now it&#8217;s very clear what is going on, since we&#8217;ve already said that &#8216;last wins&#8217;.</p>

<p>Another scenario is the reverse of the one we&#8217;ve just seen; the author actually wants to use
the FOAF property inside <em>this</em> mark-up. To achieve this they could once again use <code>@profile</code>
on the element to override the previously set profile:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">typeof=</span><span class="s">&quot;Person&quot;</span> <span class="na">profile=</span><span class="s">&quot;http://rdf.data-vocabulary.org/profile/2009&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;name&quot;</span> <span class="na">profile=</span><span class="s">&quot;http://xmlns.com/foaf/0.1/profile&quot;</span><span class="nt">&gt;</span>John Smith<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    .
</span><span class='line'>    .
</span><span class='line'>    .
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Alternatively, they could spell out the URI in full, as we saw before. But another interesting
approach is to use another token, and there are a couple of ways this could be done.</p>

<p>One way would be for authors to simply define their own token in the document. In this example
the author creates <code>foaf-name</code> to distinguish it from <code>name</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">typeof=</span><span class="s">&quot;Person&quot;</span> <span class="na">profile=</span><span class="s">&quot;http://rdf.data-vocabulary.org/profile/2009&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nt">&lt;span</span> <span class="na">property=</span><span class="s">&quot;foaf-name&quot;</span><span class="nt">&gt;</span>John Smith<span class="nt">&lt;/span&gt;</span>
</span><span class='line'>    .
</span><span class='line'>    .
</span><span class='line'>    .
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>However, a better way would be for the profile&#8217;s authors to have included a suitable prefix in
the profile itself. For example, Google&#8217;s profile might look like this (note the declaration of
<code>v</code>):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;body</span>
</span><span class='line'> <span class="na">xmlns:Person=</span><span class="s">&quot;http://rdf.data-vocabulary.org/#Person&quot;</span>
</span><span class='line'> <span class="na">xmlns:name=</span><span class="s">&quot;http://rdf.data-vocabulary.org/#name&quot;</span>
</span><span class='line'> <span class="err">.</span>
</span><span class='line'> <span class="err">.</span>
</span><span class='line'> <span class="err">.</span>
</span><span class='line'><span class="nt">&gt;</span>
</span><span class='line'>    <span class="c">&lt;!-- Some documentation about the profile here, to make it human readable. --&gt;</span>
</span><span class='line'><span class="nt">&lt;/body&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now not only are <code>Person</code> and <code>name</code> available to authors who use this profile, but so is <code>v</code>.
This means that authors can use <code>v:Person</code> if they ever need to be clear about what they are
doing.</p>

<h3>Conclusion</h3>

<p>The <code>profile</code> attribute is an obvious way to allow data publishers and data consumers to agree
on what is being published. It is sufficiently open to allow it to be used in both RDFa and
Microformats, but its definition also leaves open a way to implement &#8216;follow your nose&#8217; token
retrieval.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Treating URIs as strings considered dangerous]]></title>
    <link href="http://markbirbeck.com//blog/2010/01/18/treating-uris-as-strings-considered/"/>
    <updated>2010-01-18T00:00:00+00:00</updated>
    <id>http://markbirbeck.com//blog/2010/01/18/treating-uris-as-strings-considered</id>
    <content type="html"><![CDATA[<p>Since URIs are often conveyed as strings it&#8217;s tempting to manipulate them as
such, but it&#8217;s better&#8211;and safer&#8211;to delegate URI manipulation to special
functions. These can then have their own unit-tests, which will take into
account the edge-cases that can catch us out.</p>

<!-- more -->


<p>I&#8217;ve just been doing a quick code review in the Ubiquity XForms project, and
one thing caught my eye that I thought might be worth a post.</p>

<h2>Forms submission</h2>

<p>In forms submission &#8211; both in XForms and HTML forms &#8211; we often need to add
parameters to a URI.</p>

<p>For example, if we have the URI <code>http://example.org</code>, and the parameters <code>a=b</code>
and <code>c=d</code>, then the resulting URI should be:</p>

<p>http://example.org?a=b&c;=d</p>

<p>It seems pretty straightforward that we need to add the parameters to the URI,
with a &#8216;?&#8217; in between:</p>

<p>[uri] + &#8216;?&#8217; + [parameters]</p>

<h2>Adding parameters</h2>

<p>We can see that the parameters themselves have been added by taking the name
and value (<code>a=b</code>, etc.), and adding it to the URI, ensuring that for all
parameters other than the first, there is a separator between. (The separator
can be either an &#8216;&amp;&#8217; or a &#8216;;&#8217;.)</p>

<h2>Base URIs already containing parameters</h2>

<p>The bug that needed fixing though, was that this &#8216;naive&#8217; concatenation doesn&#8217;t
work if the URI you are dealing with already contains parameters.</p>

<p>For example, if we have the URI <code>http://example.org?x=y</code>, and we need to add
the same two parameters we had before, then our simple concatenation would
give us:</p>

<p>http://example.org?x=y?a=b&c;=d</p>

<p>when what we actually need is:</p>

<p>http://example.org?x=y&a;=b&c;=d</p>

<p>As you can see, if we already have a &#8216;?&#8217; then we don&#8217;t need to add another, so
it seems that a simple addition to our concatenation code would be to use a
call to <code>indexOf</code> to see if there is a &#8216;?&#8217; present, and only add another if we
don&#8217;t find one.</p>

<p>There&#8217;s a small additional test we&#8217;ll need to make which is to check whether
the last character in the URI is a &#8216;?&#8217;, as I&#8217;ll explain.</p>

<h2>Base URIs with empty query strings</h2>

<p>Recall that we added the parameters by placing <code>a=b</code> and <code>c=d</code> onto the end of
the URI, separated by &#8216;&amp;&#8217;:</p>

<p>http://example.org?a=b&c;=d</p>

<p>Now, if we already have a URI with a query then we need to ensure that there
is an additional &#8216;&amp;&#8217; placed before our first parameter:</p>

<p>http://example.org?x=y&a;=b&c;=d</p>

<p>But what if the base URI has a query indicator (i.e., the &#8216;?&#8217;) but no
parameters? In other words, what if we have this URI:</p>

<p>http://example.org?</p>

<p>In this situation we <em>don&#8217;t</em> want to add the extra separator, otherwise we&#8217;ll
get this:</p>

<p>http://example.org?&a;=b&c;=d</p>

<p>So our rules now become that we only want to precede our parameters with a
separator if the &#8216;?&#8217; is not the last character in the URI. It&#8217;s a little
awkward, but thanks to <code>lastIndexOf</code>, I&#8217;m sure we can manage.</p>

<h2>Base URIs already containing fragments</h2>

<p>However, there&#8217;s a further subtlety; what if the URI contains a fragment
identifier?</p>

<p>For example, if we have the URI <code>http://example.org#x</code>, and we need to add the
same two parameters we had before, then our simple concatenation would give us
this:</p>

<p>http://example.org#x?a=b&c;=d</p>

<p>The fragment identifier part of the URI has now become <code>x?a=b&amp;c;=d</code> because
it&#8217;s always the last part of the URI. What we actually want is to insert the
new parameters <em>before</em> the &#8216;#&#8217;:</p>

<p>http://example.org?a=b&c;=d#x</p>

<p>Now we need to add another use of <code>indexOf</code> to check for a &#8216;#&#8217;, and if we find
one, use its position as the point at which to insert the parameters.</p>

<h2>Context is everything</h2>

<p>However, the assumption behind using <code>indexOf</code> and <code>lastIndexOf</code> in this way
is that a URI will contain only one &#8216;?&#8217;. A secondary assumption here is that
the only time you&#8217;ll ever see a &#8216;? is as an indicator of the query part of the
URI.</p>

<p>Both of these assumptions are incorrect.</p>

<h3>Question marks in parameters</h3>

<p>The first assumption is that you can only have one &#8216;?&#8217; in a URI. However, <a href="http://labs.apache.org/webarch/uri/rfc/rfc3986.html#query">the
query section of RFC
3986</a> explicitly
flags up that the &#8216;?&#8217; character is a valid parameter value. For example, we
can have <code>a=finished?</code> as a parameter.</p>

<p>This means it&#8217;s quite easy to envisage scenarios where there is more than one
&#8217;?&#8217; in the URI:</p>

<p>http://example.org?a=finished?&c;=d</p>

<p>This won&#8217;t necessarily mess up our first use of <code>indexOf</code>, but it will mess up
the use of <code>lastIndexOf</code> as a way to check whether you need to add an extra
separator. Recall that we wanted to avoid turning this:</p>

<p>http://example.org?</p>

<p>into this:</p>

<p>http://example.org?&a;=b&c;=d</p>

<p>so we used <code>lastIndexOf</code> to check whether the last character in the URI was a
&#8217;?&#8217;. But that algorithm will turn this:</p>

<p>http://example.org?a=finished?</p>

<p>into this:</p>

<p>http://example.org?a=finished?c=d</p>

<p>You might need to look closely to spot it, but because the last character was
a &#8216;?&#8217;, we haven&#8217;t added a separator before the <code>c</code>, and as a result, instead
of having two parameters (<code>a=finished?</code> and <code>c=d</code>) we have only one
(<code>a=finished?c=d</code>).</p>

<h3>Question marks in fragments</h3>

<p>The interesting thing about the previous examples is that at least you know
you have a query string, so you might be tempted to still use <code>indexOf</code> to
manipulate things. After all, although we may have too many &#8216;?&#8217; characters, we
still know that we have query.</p>

<p>However, with the <a href="http://labs.apache.org/webarch/uri/rfc/rfc3986.html#fragment">the fragment section of RFC
3986</a> all bets
are off; here we can see that &#8216;?&#8217; is explicitly allowed as a fragment
character.</p>

<p>This means that it&#8217;s possible to have a &#8216;?&#8217; in a URI <em>even if it doesn&#8217;t have
a query</em>. For example:</p>

<p>http://example.org#finished?</p>

<p>This may seem like a contrived example, but actually it&#8217;s not, for two
reasons.</p>

<p>The first is that the fragment part of a URI is carefully defined to allow
anything, because we don&#8217;t know how it will be interpreted. You may think that
&#8220;finished?&#8221; is not valid as an HTTP fragment, but what about in the scheme
&#8220;xyz&#8221;?</p>

<p>And this is the key point; since HTML forms and XForms can ultimately deal
with any scheme, since that&#8217;s how the web is designed, we must write our
algorithms defensively, and not assume anything.</p>

<h2>Safe URI handling</h2>

<p>Hopefully this delving into some of the subtleties of URI handling and parsing
&#8211;and we haven&#8217;t even begun to talk about turning relative paths into absolute
paths, handling encoded characters, and so on&#8211; has done enough to convince
you that you shouldn&#8217;t manipulate URIs directly, as simple strings.</p>

<p>The only way to be completely sure of what is happening is to use special
functions to unpack a URI into its various components, then manipulate those
components&#8211;perhaps adding additional parameters to the list of query
parameters, but it might also be to turn a relative path into an absolute path
&#8211;before finally reassembling the URI.</p>

<p>This may sound like a lot of work, but it&#8217;s the only way to be sure that
characters don&#8217;t get incorrectly interpreted as a consequence of their
position in the URI not being taken into account.</p>

<p>In the <a href="http://backplanejs.googlecode.com/">backplanejs library</a> these
functions are in the URI module. (This is also imported into the <a href="http://ubiquity-xforms.googlecode.com/">Ubiquity
XForms library</a>.) Breaking up a URI
simply involves calling <code>spliturl</code>, which returns an object containing all of
the parts. For example:</p>

<p>spliturl( &#8220;http://example.org?a=finished?&#8221; )</p>

<p>would give us the object:</p>

<p>{</p>

<p>scheme: &#8220;http:,</p>

<p>authority: &#8220;example.org&#8221;,</p>

<p>path: &#8220;&#8221;</p>

<p>query: &#8220;a=finished?&#8221;</p>

<p>fragment: &#8220;&#8221;</p>

<p>}</p>

<p>It&#8217;s then an easy matter to manipulate the query part, before creating a new
URI with the <code>recomposeURI</code> method.</p>

<h2>Conclusion</h2>

<p>Since URIs are often conveyed as strings then it&#8217;s tempting to manipulate them
as such. But the problem with doing this means that the context of a character
is rarely taken into account when processing.</p>

<p>It&#8217;s better&#8211;and safer&#8211;to delegate URI manipulation to special functions.
These can then have their own unit-tests, which will take into account the
edge-cases that can catch us out.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Joys of Mercurial]]></title>
    <link href="http://markbirbeck.com//blog/2009/12/18/joys-of-mercurial/"/>
    <updated>2009-12-18T00:00:00+00:00</updated>
    <id>http://markbirbeck.com//blog/2009/12/18/joys-of-mercurial</id>
    <content type="html"><![CDATA[<p>No-one needs to be told that any project you work on needs a version-control
system. Nowadays, even when writing documents or OWL ontologies, I&#8217;ll use
source control, and if it&#8217;s something that can be shared with others, then I
might even start up a new Google Code project, so that I have a wiki and
issue-tracking, too.</p>

<!-- more -->


<p>Up until a few months ago, my VCS of choice was SVN, and it served us well.
But more recently I decided to give a distributed version-control system a
try, and to my surprise found not only something that could track my work, but
something that facilitated a new way of working.</p>

<h2>Choosing a DVCS</h2>

<p>The two main contenders seemed to be Mercurial and Git, although there are
definitely others. As far as I can tell, Git is the more advanced of the two,
and I was about to start using it when I discovered that Google Code supported
Mercurial. Since the differences between the two are not that great, and since
I&#8217;ve always been of the opinion that time spent trying to choose the &#8216;best&#8217; is
would be better spent getting on and learning, I plumped for Mercurial.</p>

<p>But I&#8217;d like to stress that even if Git and Mercurial were worlds apart, it
wouldn&#8217;t make much difference, because the significant difference between
these two and SVN is that it makes for a completely difference workflow.</p>

<h2>Source-control as backup, and the problem of code reviews</h2>

<p>For many years I&#8217;ve seen VCS as essentially a kind of &#8216;back up&#8217;. It&#8217;s a way of
storing the code that matches a particular release of your software, so that
you can go back to it if a customer spots a bug. It&#8217;s also a central location
that is authoritative for your code-base.</p>

<p>But over the last year or so, I&#8217;ve found that this model doesn&#8217;t really help
when it comes to managing code that is contributed to a project. If you allow
many programmers to commit to the project, then the history becomes a mish-
mash of comments about fixed bugs, branches, code reviews, and so on.</p>

<p>For example, a common problem is that inexperienced programmers will commit
too much code at a time, for review. Contributions will invariably include a
mixture of basic tidying up &#8211; such as switching tabs and spaces, removing
erroneous comments, or ensuring that code conforms to a house style &#8211; some
bug fixes that were spotted &#8216;whilst I was there&#8217;, and then of course the
proper fix itself.</p>

<p>Of course, more experienced programmers will split these elements into
separate commits, so that reviewers can focus on just what has changed. But
with a tool like SVN, this is actually quite difficult to manage.</p>

<p>For example, imagine that you start work on fixing issue 123. You add your
tests, add some code, and things are going quite well. You discover some old
comments that are no longer relevant, and delete them. You see that some of
the code doesn&#8217;t conform to the house-style, and you fix that. And then as
often happens, you realise that to fix issue 123, you actually need to add
support for something else that no-one had thought of before; you dive into
that, and add your tests.</p>

<p>Ideally you should submit code for two reviews now; the whitespace and coding
style changes can usually go straight into trunk, but the new feature and the
fix for issue 123 should be submitted for review.</p>

<p>But how to separate them?</p>

<h2>Mercurial as a patch-manager</h2>

<p>The answer is of course, creating a set of patches, and getting those
reviewed, but although &#8216;mastering patches&#8217; has been on my long list of things
to do for quite a while now, I&#8217;d never quite got round to it.</p>

<p>So it came as quite a surprise to discover that a key feature of Mercurial is
its ability to manage patches &#8211; this moves version control out of the
category of a backup system, and into a crucial part of the programmer&#8217;s
toolbox. Programmers can now &#8216;craft&#8217; their patches for submission, grouping
different pieces of work together in one patch, and then submitting them for
review. Rather than fighting against the VCS, the system helps them to get
their code ready.</p>

<p>In Mercurial for example, I can use <code>hg qrecord</code> to interactively create three
patches from the mixture of changes that I described a moment ago. Or if the
changes are in separate files, I can create patches that only contain certain
files, by using the <code>-X</code> and <code>-I</code> options on <code>hg qnew</code>.</p>

<p>But once you know what you are doing with patches, it really becomes even
easier, as I&#8217;ll illustrate.</p>

<p>My favourite way to work now is to create a basic housekeeping patch at the
beginning:</p>

<p>hg qnew housekeeping</p>

<p>Then I create a patch for the code I want to work on:</p>

<p>hg qnew issue-123 -m &#8220;Fix issue 123.&#8221;</p>

<p>We work away on our changes to the code, adding our tests and so on, and then
when we want to save those changes to our patch, we simply use the <code>qrefresh</code>
command:</p>

<p>hg qrefresh</p>

<p>Then we spot some whitespace issues, and perhaps a few unused variables.
Rather than making the changes there and then, we &#8216;unapply&#8217; our current patch
&#8211; the one that contains all of the changes to fix issue 123 &#8211; by using the
<code>qpop</code> command:</p>

<p>hg qpop</p>

<p>Our entire working directory is now back to where it was when we created the
&#8216;housekeeping&#8217; patch, but all of our changes for &#8216;issue-123&#8217; are safely stored
in a patch, waiting to be reapplied. And any changes that we make now, by
using the <code>qrefresh</code> command, will automatically be placed into the
&#8216;housekeeping&#8217; patch, rather than the &#8216;issue-123&#8217; patch. As you can see
Mercurial is helping us manage our patches, as we try to get them ready for
code review.</p>

<p>Once we&#8217;ve made our housekeeping changes, we can reapply our &#8216;issue-123&#8217;
patch, by using the <code>qpush</code> command:</p>

<p>hg qpush</p>

<p>The working directory now reflects all of the changes that we had been working
on before.</p>

<p>A slightly more complicated scenario arises when we realise that the work we
are doing should really be a separate piece of work. The easiest scenario is
when we&#8217;ve added a file or two, but realise it&#8217;s not really about &#8216;issue-123&#8217;,
but</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[RDFa and SEO]]></title>
    <link href="http://markbirbeck.com//blog/2009/12/16/rdfa-and-seo/"/>
    <updated>2009-12-16T00:00:00+00:00</updated>
    <id>http://markbirbeck.com//blog/2009/12/16/rdfa-and-seo</id>
    <content type="html"><![CDATA[<p>I did a couple of talks at SemTech 2009 this year, and although I managed to
upload my talk on <a href="http://markbirbeck.com//blog/2009/06/slides-for-semtech2009-talk-on-rdfa">RDFa: The Semantic Web&#8217;s Missing Link</a>,
I never got round to uploading the slides for a panel discussion I was involved
in, called <a href="http://semtech2009.com/session/2049/">A Shift in SEO</a>.</p>

<!-- more -->


<p>I was reminded of this omission earlier this week, when a discussion around
RDFa and SEO started to take off, fuelled largely by the energetic Martin Hepp
(see <a href="http://www.slideshare.net/mhepp/goodrelations-rdfa-for-deep-comparison-shopping-on-a-web-scale">GoodRelations &amp; RDFa for Deep Comparison Shopping on a Web Scale</a>
and <a href="http://www.seroundtable.com/archives/021266.html">Developments in Information Retrieval on the Web</a> from SES Chicago &#8216;09).</p>

<p>Since I made some points in the panel discussion that complement some of those
that are being made now, I thought &#8216;better late than never&#8217;, and <a href="http://www.slideshare.net/mark.birbeck/rdfa-in-seo">uploaded the slides</a>. (Especially since
it was quite smart of the conference organisers to place an SEO session into
the middle of a semantic technology conference.)</p>

<p>My comments in the session looked at:</p>

<ol>
<li><p>how RDFa can help to improve the display of search results;</p></li>
<li><p>how it can also be used to improve the accuracy of those results;</p></li>
<li><p>and consequently, how RDFa could help to create a series of vertical search engines.</p></li>
</ol>


<h2>Improving display of results</h2>

<p>This is the area that has probably seen most discussion recently, in the
context of Yahoo!&#8217;s enhanced results, and Google&#8217;s rich snippets. Both
techniques improve the display of search results by bringing to the fore
information that is specific to the item being displayed. For example, if the
search result is a film, then the kind of information that should be
emphasised would be whether reviewers liked the film or not, the running time,
its rating (i.e., whether it&#8217;s suitable for children, or not), which cinemas
are showing the film near you, and so on.</p>

<p>The benefits to the search engine of doing this, are that users can get more
done, on their site, making them more likely to return. The benefits for the
companies providing the data are improved click-through.</p>

<p>This last point is worth stressing, since many people on the outside of SEO
assume that it&#8217;s all about trying to get a particular web-site to appear as
high in the listings as possible, but for many sites, click-through is
probably more important than ranking. Some SEO experts at the conference were
saying that even if adding RDFa to a site gave an improvement in click-through
of only a couple of percent, sites would see that as worth the effort &#8211; yet
as Peter Mika said in <a href="http://www.semantic-conference.com/session/1723/">Year of the Monkey: Lessons from the first year of SearchMonkey</a>,
adding RDFa and Microformats to a page gives significantly better click-through
than a mere few percent.</p>

<p>Hence the interest in Martin&#8217;s <a href="http://purl.org/goodrelations/">GoodRelations ontology</a>.</p>

<h2>Improved search accuracy</h2>

<p>Search accuracy is important in this, too. Obviously it&#8217;s beneficial for the
users of search engines, in that it can help them to find the information they
want, faster. But it&#8217;s also significant for site creators and SEO
practitioners, because it means that sites are increasingly found in the right
place.</p>

<p>Once again, this seems to be at odds with the general view of SEO, but an
increasing part of the SEO job description is the writing of relevant articles
on topics that relate to your products and services, as a way to bring people
to your site. Since the search engines are increasingly clever enough to
differentiate between a bunch of keywords dumped into a page, and an article
with real content, a virtuous circle is created, rewarding &#8216;proper&#8217; articles
with improved rankings.</p>

<p>RDFa can help this further, because it allows authors to make their pages
unambiguous. And if the search engines are rewarding accuracy of ordinary text
pages, it makes sense that they&#8217;ll reward accuracy even more, if those pages
contain RDFa.</p>

<h2>Vertical search engines</h2>

<p>The final point I looked at was the way that RDFa will allow the search giants
to offer partitioned search engines, aimed at particular audiences.</p>

<p>It&#8217;s true that there are many search engines already available, for specialist
areas, but most of them tend to be out of date, or missing information
altogether, and they often require bloggers to register their site for
crawling.</p>

<p>The major search engines are often crawling these sites already anyway, but
page ranking algorithms will hide them away in the 1000th page of your search
results. By adding targeted mark-up to web-pages it becomes easier for search
engines to differentiate the subject-matter of the pages, and so offer
specialised views on their data.</p>

<h2>Conclusion</h2>

<p>RDFa is already impacting search in positive ways, and SEO is adapting
accordingly. But there is a great deal further that search and SEO can go
towards being more &#8216;semantic&#8217;, and RDFa has a lot to offer in realising the
potential.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Linked Data and RDFa in US and UK government web-sites]]></title>
    <link href="http://markbirbeck.com//blog/2009/11/20/linked-data-and-rdfa-in-us-and-uk/"/>
    <updated>2009-11-20T00:00:00+00:00</updated>
    <id>http://markbirbeck.com//blog/2009/11/20/linked-data-and-rdfa-in-us-and-uk</id>
    <content type="html"><![CDATA[<p>Two exciting pieces of RDFa news arrived within ten minutes of each other in
my Twitter client. Both concerned governments making data open &#8211; one in the
US, and the other in the UK.</p>

<!-- more -->


<p>The first item was a reference by Steven Pemberton
(<a href="http://twitter.com/stevenpemberton">@stevenpemberton</a>) to <a href="http://www.informationweek.com/news/government/info-management/showArticle.jhtml?articleID=221900361">a story in
Information Week</a>,
which explained that the new media team at the Whitehouse plan to use more
RDFa in their pages. Scanned PDFs are no longer good enough, according to
deputy director David Cole.</p>

<p>The second item came via Andrew Lewin (<a href="http://twitter.com/draml">@draml</a>),
and concerns the release by the COI of <a href="http://coi.gov.uk/guidance.php?page=312">guidance on how to mark-up vacancies and consultations</a>
with RDFa, which I&#8217;m pleased to say I helped to write.</p>

<p>This latter announcement is particularly exciting for RDFa, for a number of
reasons.</p>

<p>First, it&#8217;s a real-world usage of the syntax; it&#8217;s not an announcement of
something that someone, somewhere, hopes to do in the future &#8211; the vocabulary
is there, servers are deployed, and this is a set of instructions to people
who produce government web-sites on how they should mark up their pages if
they want their data to be consumed.</p>

<p>Second, it&#8217;s exciting because the use of RDFa is extremely leading-edge. Of
course it&#8217;s great to see people groking RDFa as a way to do things like
improve search, but the COI realised long ago that RDFa could also be used as
a mechanism to ease the publishing and centralisation of data. This is
something that I think we can expect to see more of, in the coming year.</p>

<p>(A full description of the project can be found at <a href="http://markbirbeck.com//blog/2009/04/23/more-rdfa-goodness-from-uk-government-web-sites">More RDFa goodness from UK
government web-sites</a>.
It&#8217;s also discussed in <a href="http://markbirbeck.com//blog/2009/07/talking-with-mark-birbeck-about-rdfa-and-its-use-in-government">Mark Birbeck interviewed by Paul Miller about RDFa</a>.)</p>

<p>And finally, I find this announcement exciting because the guidelines document
uses the term &#8216;Linked Data&#8217; throughout. This reflects an extremely deep
understanding of the implications of what COI are doing with RDFa; the COI do
not simply explain to people how to publish vacancies and consultations to the
web &#8211; they are describing how to publish that data <em>to the Linked Data
cloud</em>. The introduction is forthright on this:</p>

<blockquote><p>Government is committed to making its public information and data as widely
available as possible. The best way to make structured information available
online is to publish it as Linked Data. Linked Data makes the information
easier to cut and combine in ways that are relevant to citizens. This document
describes how to put government consultations information into Linked Data.</p></blockquote>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Evangelising RDFa in Australia]]></title>
    <link href="http://markbirbeck.com//blog/2009/10/21/evangelising-rdfa-in-australia/"/>
    <updated>2009-10-21T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/10/21/evangelising-rdfa-in-australia</id>
    <content type="html"><![CDATA[<p>I was recently lucky enough to take my first trip to Australia. I was there to
do two talks, the first on RDFa and its use in Government (given in Canberra,
the home of the Australian government), and the second, a talk on RDFa and its
impact on the web (given at the Web Directions South 2009 conference).</p>

<!-- more -->


<p>I&#8217;ve embedded the presentations below, although it&#8217;s probably better to view
the presentations at SlideShare, so that you can see the speaker notes:</p>

<p><a href="http://www.slideshare.net/mark.birbeck/rdfa-and-%0Agovernment-data">RDFa and Government Data</a></p>

<p>View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/mark.birbeck">Mark
Birbeck</a>.</p>

<p><a href="http://www.slideshare.net/mark.birbeck/rdfa-what-happens-when-pages-%0Aget-smart">RDFa: What happens when web-pages get
smart?</a></p>

<p>View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/mark.birbeck">Mark
Birbeck</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[RDFa down under]]></title>
    <link href="http://markbirbeck.com//blog/2009/10/01/rdfa-down-under/"/>
    <updated>2009-10-01T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/10/01/rdfa-down-under</id>
    <content type="html"><![CDATA[<p>I&#8217;m really looking forward to my first ever visit to Australia, starting
Sunday. Whilst it would have been fun to do the trip with the family, it&#8217;s a
close second that I&#8217;ve been invited there by W3C Australia, to speak about
RDFa.</p>

<!-- more -->


<p>I&#8217;ll be doing a few informal workshops, and a couple of public talks, as well
as taking in <a href="http://webweek.com.au/">Australian Web Week</a>.</p>

<p>The first public talk is on Wednesday, at the Australian National University
in Canberra, on <a href="http://www.w3c.org.au/newsandevents/index.php/2009/09/29/seminar-%0Ardfa-and-its-use-in-government-mark-birbeck-uk-7-october-2009">RDFa and its use in
government</a>. Whilst I&#8217;ll be
using some of the <a href="http://markbirbeck.com//mark-birbeck/blog/2009/04/23/more-%0Ardfa-goodness-from-uk-government-web-sites">UK government projects</a> I&#8217;ve worked on to illustrate my
points, it will also be interesting to hear what attendees have to say about
the recently launched <a href="http://data.australia.gov.au/">data.australia.gov.au</a>.</p>

<p>Later in the week I&#8217;ll be at the Web Directions South conference in Sydney,
where I&#8217;ll be talking about <a href="http://south09.webdirections.org/program/w3ctrack#marking-up-content-%0Awith-rdfa">Marking up content with
RDFa</a>, in the W3C track.</p>

<p>And to round the whole thing off I&#8217;ll get the chance to finally meet in
person, some of the people who I&#8217;ve been reading over the years, such as David
Peterson, Laurent Lefort and John Allsopp.</p>

<p>All in all, it looks like it will be a busy and exciting week.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[RDFa Tech Talk, at Google, 2009]]></title>
    <link href="http://markbirbeck.com//blog/2009/09/21/rdfa-tech-talk-at-google-2009/"/>
    <updated>2009-09-21T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/09/21/rdfa-tech-talk-at-google-2009</id>
    <content type="html"><![CDATA[<p>Although my talk <em>Beyond Web 2.0 &#8211; How RDFa Can Help to Democratise Data on
the Web</em>, took place back in June, it&#8217;s only just now been made available
online, due to technical problems.</p>

<!-- more -->


<p>(I should say too, that those same technical problems also mean that the video
is in 50&#8217;s style black and white; maybe it gives it a bit more authority.)</p>

<p>I really enjoyed the session, and you&#8217;ll hear at one point near the end I get
to put some questions to Othar Hansson and Kavi Goel, and the rest of the Rich
Snippets team, about how they&#8217;ll be using RDFa going forwards.</p>

<p>Many thanks to T. V. Raman for having me back, and of course, for the Google
lunch.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[XForms Developer Zone and User Group launched]]></title>
    <link href="http://markbirbeck.com//blog/2009/09/15/xforms-developer-zone-and-user-group/"/>
    <updated>2009-09-15T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/09/15/xforms-developer-zone-and-user-group</id>
    <content type="html"><![CDATA[<p>We&#8217;re pleased to be launching two new initiatives to help people who are
interested in XForms.</p>

<!-- more -->


<p>The first is the all new XForms Developer Zone web-site &#8211; or
<a href="http://xformsdz.org">xformsdz</a>, as we&#8217;re calling it.</p>

<p>Whilst the Developer Zone will be unashamedly biased towards XForms, within
that, we&#8217;ll have discussions, articles, code snippets, and tutorials about any
XForms processor we can find, and any application framework in which it&#8217;s
used.</p>

<p>To accompany the web-site, we&#8217;re also launching a regular newsletter, and a
London XForms User Group.</p>

<h2>The London XForms User Group</h2>

<p>The <a href="http://www.meetup.com/london-xforms-user-%0Agroup/calendar/11102461/">inaugural meeting</a> of the user group will be in Clerkenwell, London,
hosted by Skills Matter. We&#8217;ll be looking at the architecture of XForms, in
particular what it means to have MVC support built in from the ground up, and
we&#8217;ll be using <a href="http://xformsdz.org/article/2009/09%0A/easy-map-controls-ubiquity-xforms">XForms and Google Maps</a> as a case-study.</p>

<p>The October meeting will look at the <a href="http://www.meetup.com/london-xforms-user-%0Agroup/calendar/10787076/">benefits of using XForms for the UK
insurance industry</a>, and we&#8217;re lucky enough to have an industry expert
&#8211; Neal Champion &#8211; speaking to us that evening.</p>

<p>If you&#8217;d like to come along, we&#8217;d love to see you. And even if you can&#8217;t make
it, <a href="http://www.meetup.com/london-xforms-%0Auser-group/">join the user group mailing-list</a>, and we&#8217;ll keep you posted about XForms-related activities and
events, in and around London.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Linking issues and revisions in Google Code]]></title>
    <link href="http://markbirbeck.com//blog/2009/08/23/linking-issues-and-revisions-in-google/"/>
    <updated>2009-08-23T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/08/23/linking-issues-and-revisions-in-google</id>
    <content type="html"><![CDATA[<p>We use <a href="http://code.google.com/">Google Code</a> a lot in our projects, because
it provides a great range of tools, with a straightforward interface.</p>

<p>It&#8217;s particularly useful to have version control and issue-tracking in the
same system, and it&#8217;s very easy to cross-reference the two by referring to
revisions in issue comments, and to issues in the commit messages.</p>

<!-- more -->


<p>On top of that, Google Code provides some nice code review facilities, and
here too, it&#8217;s possible to refer back to revisions and issues.</p>

<p>In this post I&#8217;ll outline how we use these tools together in UXF, the
<a href="http://ubiquity-xforms.googlecode.com/">Ubiquity XForms AJAX library</a>.</p>

<h2>Everything should have an issue</h2>

<p>The first thing that&#8217;s needed is an issue. This might be an issue in the
traditional sense, of a bug. But it might also be a desirable feature, that
someone would like to add. Whatever it is, we shouldn&#8217;t really be starting to
code until we&#8217;ve written down what we&#8217;re going to do, or what problem we&#8217;re
trying to solve.</p>

<p>Let&#8217;s use <a href="http://code.google.com/p/ubiquity-%0Axforms/issues/detail?id=515">issue 515</a> as an illustration. At the top we see it has the
following description:</p>

<pre><code>  We need a UI control that can adhere to data binding restrictions for   
  xsd:boolean / xforms:boolean. The control may render a checkbox, for   
  example.  

  Sample code snippet:  

      &lt;xf:input ref="check" datatype="xforms:boolean"&gt;  
        &lt;xf:label&gt;Check: &lt;/xf:label&gt;  
      &lt;/xf:input&gt;  

  Based on conversation with John in last week's call, needed in this   
  iteration (setting priority to critical).  
</code></pre>

<h2>Code reviews and issues</h2>

<p>This description is plenty to get started with, so
<a href="http://code.google.com/u/rahul.akolkar/">Rahul</a> gets on with his development
and testing, until he is ready for a code review. When he is ready, he commits
his code to the review area, with the following SVN message:</p>

<pre><code>  [ issue 515 ] Proposed changes for adding a UI control that can bind to boolean  
  data (renders a checkbox).  
</code></pre>

<p>You can view this commit at <a href="http://code.google.com/p/ubiquity-%0Axforms/source/detail?r=2919">r2919</a>, and as you can see, Google Code provides a
convenient link to all of the files involved in the commit. GC also provides
tools for attaching comments to any line in those files.</p>

<p>This revision therefore becomes the location at which the review is conducted,
perhaps involving many comments from many reviewers.</p>

<p>But note also that Rahul&#8217;s reference to &#8220;issue 515&#8221; has become a link to the
issue itself. This means that a reviewer has everything they need to start
reviewing &#8211; links to all of the files that have changed, a reference to the
issue being addressed, and some tools that allow them to add comments to the
files.</p>

<p>However, anyone viewing the issue directly would not necessarily know that it
was being worked on, or what the progress was. So to keep things up-to-date,
Rahul added the following comment to issue 515:</p>

<pre><code>  Code for such a UI control has been proposed for addition in r2919 and review   
  requested. Changing Status to InReview.  
</code></pre>

<p>The issue is now not only marked as being <code>InReview</code>, but we also have a
convenient link to the code review itself. If you were interested in this
issue, you would now be able to add your comments to the review, try out the
proposed code, and so on.</p>

<h2>Committing the code to trunk</h2>

<p>At some point the review will finish, and the code will be ready to go into
the trunk. (There may be other reviews first, but at some point the cycle
should end.)</p>

<p>In our example, Rahul commits his reviewed code to trunk at
<a href="http://code.google.com/p/ubiquity-xforms/source/detail?r=2920">r2920</a>, with
the following message:</p>

<pre><code>  [ issue 515 ] UI control that can bind to boolean data. Committed after favorable  
  review of r2919, with suggested filename change.  
</code></pre>

<p>Note that we still have a reference to the issue number, but most importantly,
we have a reference to the code review at r2919. This means that anyone
looking at the code that is committed, and who wanted to understand why a
particular change was made, could find the history of the discussion in the
code review.</p>

<p>But we&#8217;re not finished yet.</p>

<p>If we go back to the code review at r2919, we&#8217;ll find that the last comment
Rahul has added says:</p>

<pre><code>  Committed to trunk in r2920.  
</code></pre>

<p>Now, anyone who stumbles across the code review directly knows that the code
they are looking at really did find it&#8217;s way into the trunk, and wasn&#8217;t left
hanging there uncommitted, or was abandoned in favour of some other solution.</p>

<h2>Closing the issue</h2>

<p>The final step is of course to close off the issue, and here it&#8217;s important to
refer to the revision at which the code was committed. In our example, the
last comment on issue 515 is this:</p>

<pre><code>  Committed to trunk in r2920 after favorable review.  

  Resolving issue as Fixed.  
</code></pre>

<p>Now anyone interested specifically in the issue can see not only that it is
closed, but also where the code is that addressed the issue.</p>

<h2>Conclusion</h2>

<p>This technique may seem a little laborious, but it actually takes longer to
describe than to do.</p>

<p>And by following these steps we ensure that we know how a sequence of comments
ends, whether in an issue or code review.</p>

<p>We need to know how an issue was addressed when it gets marked as fixed, we
need to know what happens to code after a positive code review, we need to
know where some code came from that is committed to trunk; in short, no matter
whether you are looking at one of committed code, an issue, or a code review,
these procedures ensure that you can easily find the other two.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using RDFa to Provide License Information to Google Image Search]]></title>
    <link href="http://markbirbeck.com//blog/2009/08/14/using-rdfa-to-provide-license/"/>
    <updated>2009-08-14T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/08/14/using-rdfa-to-provide-license</id>
    <content type="html"><![CDATA[<p>About a month ago, Google made it possible for anyone searching for images to
filter the results based on the license type (see <a href="http://googleblog.blogspot.com/2009/07/find-creative-commons-images-with-image.html">Find Creative Commons images with Image Search</a>). But it was only in the last couple
of days that they spelt out exactly how you can let the Google crawlers know
what licenses you are making your own images available under, in <a href="http://www.youtube.com/watch?v=quyhasVn2jw">a video by Peter Linsley, from Google Image Search</a> &#8211; which is to use RDFa.
Peter&#8217;s created a great tutorial, but it&#8217;s actually possible to mark-up
license information even more simply than he shows in his video.</p>

<!-- more -->


<h2>Introduction</h2>

<p>The tutorial begins with the code for an image tag:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image.jpg&quot;</span> <span class="nt">/&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Peter then
suggests adding a link to the relevant license, as follows:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;a</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span>
</span><span class='line'> <span class="nt">&gt;</span>Creative Commons Attribution-Share Alike 3.0<span class="nt">&lt;/a&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Peter rightly points out that with this mark-up, Google has no way to tell
whether the license applies to the page or the image &#8211; a problem that would
be compounded if there were a number of images on the same page. However, he
shows how this can be resolved by adding a container for the mark-up, and
placing an <code>@about</code> value onto that container:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">about=</span><span class="s">&quot;image.jpg&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image.jpg&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nt">&lt;a</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span>
</span><span class='line'>   <span class="nt">&gt;</span>Creative Commons Attribution-Share Alike 3.0<span class="nt">&lt;/a&gt;</span>
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>There&#8217;s nothing wrong with Peter&#8217;s approach and it will work in all
situations. But there will be many occasions where a slightly easier solution
is possible.</p>

<h2>Placing @about on the anchor</h2>

<p>This first scenario assumes that we still want the clickable link, but not the
containing <code>div</code>. In that case we need only place the <code>@about</code> value onto the
link itself, to achieve the same effect as having the container:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image.jpg&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;a</span> <span class="na">about=</span><span class="s">&quot;image.jpg&quot;</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span>
</span><span class='line'> <span class="nt">&gt;</span>Creative Commons Attribution-Share Alike 3.0<span class="nt">&lt;/a&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>The nice thing about this
technique is that the clickable link that refers to the license doesn&#8217;t need
to be directly next to the image, or even close on the page (which it does
with the container approach), which gives publishers a little more flexibility
when it comes to the document&#8217;s layout.</p>

<h2>Images and @rel</h2>

<p>If we don&#8217;t want the clickable link that points to the license, then we can
place the <code>@rel="license"</code> directly onto the image:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image.jpg&quot;</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span><span class="nt">&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is a
great solution for software tools such as editors or content management
systems, because it means that licensing information can be added to the
image, right at the point where the image is embedded into the mark-up. Not
only that, the image reference and the license are combined in a self-
contained unit that can move around the document with no side-effects.</p>

<h2>Using the same license for many images</h2>

<p>Note that if the same license is to be applied to many images, then the
containing element technique becomes useful again; we can specify a reference
to the license on the container, and then use <code>@rev</code> to make the connection
with the images:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">about=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span> <span class="na">rev=</span><span class="s">&quot;license&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image1.jpg&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image2.jpg&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image3.jpg&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image4.jpg&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>This gives Google exactly the same information as this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image1.jpg&quot;</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image2.jpg&quot;</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image3.jpg&quot;</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">&quot;image4.jpg&quot;</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span><span class="nt">&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<h2>License information in the head</h2>

<p>One final approach worth mentioning for the sake of completeness, is to place
all of the license information into the head of the document:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;head&gt;</span>
</span><span class='line'>  <span class="nt">&lt;link</span> <span class="na">about=</span><span class="s">&quot;image1.jpg&quot;</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by-sa/3.0/&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="nt">&lt;link</span> <span class="na">about=</span><span class="s">&quot;image2.jpg&quot;</span> <span class="na">rel=</span><span class="s">&quot;license&quot;</span> <span class="na">href=</span><span class="s">&quot;http://creativecommons.org/licenses/by/3.0/&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  ...
</span><span class='line'><span class="nt">&lt;/head&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>This may be
useful in some CMS systems, where all of the licensing information for any
element that appears on a particular page can simply be &#8216;dumped&#8217; into the page
in one go.</p>

<h2>Conclusion</h2>

<p>It&#8217;s great to see Google improving the user&#8217;s search experience by surfacing
license information in this way, and it&#8217;s great to see that RDFa is helping
publishers to provide this information to Google&#8217;s crawlers, however they
choose to mark it up.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using Rdfa To Provide License]]></title>
    <link href="http://markbirbeck.com//blog/2009/08/14/using-rdfa-to-provide-license/"/>
    <updated>2009-08-14T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/08/14/using-rdfa-to-provide-license</id>
    <content type="html"><![CDATA[<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<title>2009-08-14-using-rdfa-to-provide-license.html</title>

</head>

<body>

<hr />

<p>layout: post
title: &#8220;Using RDFa to Provide License Information to Google Image Search&#8221;
date: 2009-08-14
comments: false
categories:
 - mark birbeck</p>

<h2> - rdfa</h2>

<p>About a month ago, Google made it possible for anyone searching for images to
filter the results based on the license type. (See <a href="http://googleblog.blogspot.com/2009/07/find-
creative-commons-images-with-image.html">Find Creative Commons
images with Image Search</a>.) But it was only in the last couple
of days that they spelt out exactly how you can let the Google crawlers know
what licenses you are making your own images available under, in <a href="http://www.youtube.com/watch?v=quyhasVn2jw">a video by
Peter Linsley, from Google Image
Search</a> &#8211; which is to use RDFa.
Peter&#8217;s created a great tutorial, but it&#8217;s actually possible to mark-up
license information even more simply than he shows in his video.</p>

<!-- more -->

<h2>Introduction</h2>

<p>The tutorial begins with the code for an image tag:</p>

<p><code>
&lt;img src="image.jpg" /&gt;
</code></p>

<p>Peter then
suggests adding a link to the relevant license, as follows:  <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons
Attribution-Share Alike 3.0</a>
Peter rightly points out that with this mark-up, Google has no way to tell
whether the license applies to the page or the image &#8211; a problem that would
be compounded if there were a number of images on the same page. However, he
shows how this can be resolved by adding a container for the mark-up, and
placing an <code>@about</code> value onto that container:</p>

<p><img src="image.jpg" alt="" title="" /> <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike
3.0</a></p>

<p>There&#8217;s nothing wrong with Peter&#8217;s approach and it will work in all
situations. But there will be many occasions where a slightly easier solution
is possible.</p>

<h2>Placing @about on the anchor</h2>

<p>This first scenario assumes that we still want the clickable link, but not the
containing <code>div</code>. In that case we need only place the <code>@about</code> value onto the
link itself, to achieve the same effect as having the container:
<img src="image.jpg" alt="" title="" /> <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike
3.0</a> The nice thing about this
technique is that the clickable link that refers to the license doesn&#8217;t need
to be directly next to the image, or even close on the page (which it does
with the container approach), which gives publishers a little more flexibility
when it comes to the document&#8217;s layout.</p>

<h2>Images and @rel</h2>

<p>If we don&#8217;t want the clickable link that points to the license, then we can
place the <code>@rel="license"</code> directly onto the image:  <img src="image.jpg" alt="" title="" /> This is a
great solution for software tools such as editors or content management
systems, because it means that licensing information can be added to the
image, right at the point where the image is embedded into the mark-up. Not
only that, the image reference and the license are combined in a self-
contained unit that can move around the document with no side-effects.</p>

<h2>Using the same license for many images</h2>

<p>Note that if the same license is to be applied to many images, then the
containing element technique becomes useful again; we can specify a reference
to the license on the container, and then use <code>@rev</code> to make the connection
with the images:</p>

<p><img src="image1.jpg" alt="" title="" /> <img src="image2.jpg" alt="" title="" /> <img src="image3.jpg" alt="" title="" /> <img src="image4.jpg" alt="" title="" /></p>

<p>This gives Google exactly the same information as this:  <img src="image1.jpg" alt="" title="" />
<img src="image2.jpg" alt="" title="" /> <img src="image3.jpg" alt="" title="" /> <img src="image4.jpg" alt="" title="" /></p>

<h2>License information in the head</h2>

<p>One final approach worth mentioning for the sake of completeness, is to place
all of the license information into the head of the document:  This may be
useful in some CMS systems, where all of the licensing information for any
element that appears on a particular page can simply be &#8216;dumped&#8217; into the page
in one go.</p>

<h2>Conclusion</h2>

<p>It&#8217;s great to see Google improving the user&#8217;s search experience by surfacing
license information in this way, and it&#8217;s great to see that RDFa is helping
publishers to provide this information to Google&#8217;s crawlers, however they
choose to mark it up.</p>

</body>
</html>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Mark Birbeck interviewed by Paul Miller about RDFa]]></title>
    <link href="http://markbirbeck.com//blog/2009/07/10/mark-birbeck-interviewed-by-paul-miller/"/>
    <updated>2009-07-10T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/07/10/mark-birbeck-interviewed-by-paul-miller</id>
    <content type="html"><![CDATA[<p>I was lucky enough to be interviewed by Paul Miller for his weekly podcast
yesterday. We spoke about RDFa, touching on a range of topics from its goals
and how it came about, to its relationship to linked data and how it&#8217;s being
used in some recent projects for UK Government web-sites.</p>

<!-- more -->


<p>The podcast is on Paul&#8217;s <a href="http://cloudofdata.com/2009/07%0A/talking-with-mark-birbeck-about-rdfa-and-its-use-in-government/">Cloud of Data</a> site.</p>

<p>And there&#8217;s more information about the projects, in <a href="http://markbirbeck.com//mark-birbeck/blog/2009/04/23/more-rdfa-goodness-%0Afrom-uk-government-web-sites">More RDFa goodness from
UK government web-sites</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Semantic Web's Missing Link]]></title>
    <link href="http://markbirbeck.com//blog/2009/06/25/semantic-web-missing-link_25/"/>
    <updated>2009-06-25T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/06/25/semantic-web-missing-link_25</id>
    <content type="html"><![CDATA[<p>The slides from Mark Birbeck&#8217;s SemTech 2009 talk <a href="http://markbirbeck.com//mark-birbeck/blog/2009/06/slides-for-semtech2009-talk-on-rdfa">RDFa: The Semantic Web&#8217;s
missing link</a>,
are now online.</p>

<!-- more -->


<p><a href="http://markbirbeck.com//mark-birbeck/blog/2009/06/slides-for-%0Asemtech2009-talk-on-rdfa"><img src="http://markbirbeck.com//files/missing-link-slides.jpg" alt="" /></a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Seminar: The possibilities of RDFa and the Semantic Web]]></title>
    <link href="http://markbirbeck.com//blog/2009/06/18/seminar-possibilities-of-rdfa-and/"/>
    <updated>2009-06-18T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/06/18/seminar-possibilities-of-rdfa-and</id>
    <content type="html"><![CDATA[<p>The slides are now online of the free RDFa seminar we ran with Skills Matter,
on July 13th. A recording will also be available soon.</p>

<!-- more -->


<p>To see the presentation notes and embedded videos you&#8217;ll need to view the
presentation over at the SlideShare site (follow the link below).</p>

<p><a href="http://www.slideshare.net/mark.birbeck/the-possibilities-of-rdfa-and-the-%0Asemantic-web">The possibilities of RDFa and the Semantic
Web</a></p>

<p>View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/mark.birbeck">Mark
Birbeck</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Semantic Web's Missing Link]]></title>
    <link href="http://markbirbeck.com//blog/2009/06/16/semantic-web-missing-link/"/>
    <updated>2009-06-16T00:00:00+01:00</updated>
    <id>http://markbirbeck.com//blog/2009/06/16/semantic-web-missing-link</id>
    <content type="html"><![CDATA[<p>SemTech 2009 is turning out to be an interesting conference in many ways, and
I&#8217;ve been to some useful presentations.</p>

<!-- more -->


<p>I did the first of my presentations this morning, on RDFa, and the slides are
below. The PowerPoint itself contain speaker&#8217;s notes which will explain quite
a lot of what is going on, so if you&#8217;re interested then it&#8217;s probably worth
downloading:</p>

<p><a href="http://www.slideshare.net/mark.birbeck%0A/rdfa-the-semantic-webs-missing-link-1595482?type=powerpoint">RDFa: The Semantic Web&#8217;s Missing Link</a></p>

<p>View more <a href="http://www.slideshare.net/">OpenOffice presentations</a> from
<a href="http://www.slideshare.net/mark.birbeck">mark.birbeck</a>.</p>
]]></content>
  </entry>
  
</feed>
