I had to shift a load of bags of cement inside earlier to prevent the hard pillow syndrome. This was right after reading Tantek's iffy comment on Ian Davis' post (see also Ian's follow-up). Tantek mentioned the DRY (Don't Repeat Yourself) principle, which is generally leads to less fragile code/data. The only problem with this in the context of microformats is that if you've got a bunch of data expressed in HTML (say a company's address book), it's going to be difficult to modify in-place should the information change.
A common strategy for content management systems is to keep the content in a database, where it's easy to change, and have a templating system look after generation of HTML as a presentation layer - classic model & view separation. However CMSs commonly treat blocks of content as blobs, there's not the granularity of addressing needed for on-the-fly embedding of data.
Model & view separation makes a lot of sense in RDF systems too, and there's no problem representing the kind data microformats deal with as RDF. I was recently thinking about serializers to eRDF/RDFa, but this still wouldn't help much with all the HTML you might well want in the same document. While shifting the cement, it occurred to me that simple templating could work. So I just whipped up a bit of code to try it out.
So I've got some RDF containing some data I'd like to appear in a microformatted doc:
[ a v:VCard;
v:Name "Joe Lambda";
v:email "joe.lambda@gmail.com";
v:tel "123-123-123". ]
Doesn't matter where it came from - one source might be the result of a SPARQL CONSTRUCT query against a bunch of scuttered material.
I want this to fit into a template that looks something like this:
<div class="vcard">
<span class="fn n">
<span class="name">
{{card.v_Name}}</span>
</span>
<a class="email" xhref="mailto:
{{card.v_email}}">
{{card.v_email}}</a>
<div class="tel">
{{card.v_tel}}</div>
</div>
The required result is:
<div class="vcard">
<span class="fn n">
<span class="name">Joe Lambda</span>
</span>
<a class="email" xhref="mailto:joe.lambda@gmail.com"
mce_href="mailto:joe.lambda@gmail.com">joe.lambda@gmail.com</a>
<div class="tel">123-123-123</div>
</div>
So how do I get from data + template to microformatted result?
Easy! Using Python.
Here's the code that does the work:
p = re.compile('{{.+?}}')
def get_value(match):
return eval(match.group()[2:-2])
hcard = p.sub(get_value, template)
All it does is replace each placeholder with an evaluation of the placeholder's content. Ok, so how do I get card.v_Name to evaluate as Joe Lambda?
Easy! Using Mark Nottingham's sparta.py. It Just Works.
Here's my trial code: vcard.py, the sample RDF is built up in there programmatically (taking up most of the lines of code - that snippet above really is the functional part). Here's the sample template: vcard.template. If you want to run it you'll need a recent Python, rdflib and sparta.
Ok, it would need a fair bit of work to get it into a practical form, but I'm pleasantly surprised how straightforward it was to go from idea to a rough proof-of-concept. It's taken me just over an hour, including typing this. Most of that time was spent re-reading bits of the Python tutorial. The only RDF-related bit that took any thought at all was figuring out how Sparta does name-value pairs (functional properties, card.v_Name = "Joe Lambda") compared to regular RDF properties which can have multiple values ( card.rdf_type.add(VCard)). RDF has always been conceptually simple, when there are giants loitering around upon who's shoulders you can stand, implementation isn't hard either. (PS. if you ignore the bits needed to get the RDF & templates, this boils down to 4 lines of code - that gobsmacks me a little ;-)
PS. Michael Hausenblas beat me to it! In this mail to
public-rdf-in-xhtml-tf@w3.org,
he points to an online
FOAF/RDF to FOAF/RDFa
converter he's built, using templating. Way!
Â
@en