I am making all kind of tests for the chapter about multimedia of our upcoming Web 2.0 book and as it is often the case when I am writing, this is sparkling a number of strange ideas.
I was exploring the similarities between playlists, podcasts and SMIL animation when it occurred to me that it might be interesting to see what can be done with microformats.
Although the relEnclosure proposal still needs some polishing (for instance, it mentions that Atom requires a length on enclosures but do not define a way to express this length), the result would be something such as:
<div class="hfeed">
<h1>SVG en quinze points</h1>
<div class="hentry">
<h2 class="hentry-title">
<a
href="http://xmlfr.org/documentations/articles/i040130-0001/01%20-%20C'est%20base%20sur%20XML.mp3"
rel="bookmark" title="...">C'est basé sur XML</a>
</h2>
<p class="hentry-content">By <address class="vcard author fn">Antoine Quint</address> -
<abbr class="updated" title="2004-01-30T00:00:00">2004-01-30T00:00:00</abbr>
</p>
<p>[<a
href="http://xmlfr.org/documentations/articles/i040130-0001/01%20-%20C'est%20base%20sur%20XML.mp3"
rel="enclosure">download</a>] (<span class="htype">audio/mpeg</span>, <span
class="hLength">231469</span> bytes).</p>
</div>
.
.
.
</div>
I am not a microformat expert and I have been surprised to see that this document is actually much harder to write than the corresponding Atom document. It probably contains lots of errors and if you spot one of them, thanks to report it as a comment.
This is nice, but probably not what users would expect for a Web 2.0 application. For one thing, this page is static and lacking all the bells and whistles of a Web 2.0 application. For instance, we might want to use one of the techniques exposed by Mark Huckvale to play the audio in the web page itself.
For this, we would need to modify the document and entries could become:
<div class="hentry">
<h2 class="hentry-title">
<a
href="http://xmlfr.org/documentations/articles/i040130-0001/01%20-%20C'est%20base%20sur%20XML.mp3"
rel="bookmark" title="...">C'est basé sur XML</a>
</h2>
<p class="hentry-content">By
<address class="vcard author fn">Antoine Quint</address> - <abbr
class="updated" title="2004-01-30T00:00:00"
>2004-01-30T00:00:00</abbr>
</p>
<p>[<a
href="javascript:play("http://xmlfr.org/documentations/articles/i040130-0001/01%20-%20C'est%20base%20sur%20XML.mp3");"
rel="enclosure">play</a>] (<span class="htype"
>audio/mpeg</span>, <span class="hLength">231469</span> bytes).</p>
</div>
This is not very different, but the links with rel= »enclosure » have been replaced by a call to a Javascript function and this is enough to loose the semantic of the microformat since we obfuscate the enclosure’s URL.
We have thus a situation where the document that we want to server is different from the document that we want to display client side and that’s a typical use case for client side XSLT.
The trick is to write a simple transformation that makes the static page synamic:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml" xmlns:x="http://www.w3.org/1999/xhtml" version="1.0"
exclude-result-prefixes="x">
<xsl:output method="xml" encoding="UTF-8" indent="yes" cdata-section-elements="x:style x:script"/>
<xsl:strip-space elements="*"/>
<xsl:preserve-space elements="x:script x:style"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="x:head">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<style type="text/css"><![CDATA[
#player {
padding: 10px;
background-color: gray;
position:fixed;
top: 20px;
right:10px
}
] ]></style>
<script type="text/javascript"><![CDATA[
function play(surl) {
document.getElementById("player").innerHTML=
'<embed src="'+surl+'" hidden="false" autostart="true" loop="false"/>';
}
] ]></script>
</xsl:copy>
</xsl:template>
<xsl:template match="x:body">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<div id="player">A media player<br/>will pop-up here.</div>
</xsl:copy>
</xsl:template>
<xsl:template match="x:a[@rel='enclosure']/@href">
<xsl:attribute name="href">
<xsl:text>javascript:play("</xsl:text>
<xsl:value-of select="."/>
<xsl:text>");</xsl:text>
</xsl:attribute>
</xsl:template>
<xsl:template match="x:a[@rel='enclosure']/text()">
<xsl:text>play</xsl:text>
</xsl:template>
</xsl:stylesheet>
And add a xsl-stylesheet PI to the static (microformat) page:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="decorateMf.xsl" type="text/xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml">
.
.
.
</html>
This is working fine for me (GNU Linux/Ubuntu, Firefox 1.5) and the mplayer plug-in nicely pops up in the player div when I click on one of the « play » links but it would require a bit of polishing to work in other browsers:
- The page crashes Opera 9.0 (I have entered a bug report and have been contacted back by their tech support who is already working on the issue).
- The XSLT output method needs to be changed to HTML to work in Internet Explorer (otherwise the result is displayed as a XML document). Furthermore, IE inserts the embed element as text in the player div and you might need to use a proper DOM method to insert the embed element as a DOM node.
[Try it!]
There are probably a number of other (easier?) solutions for the specific problem I have solved here. However, this is an interesting pattern to apply in situations where you want to serve a clean document that needs to be altered to display nicely in a browser.
XSLT has sometimes been described as a « semantic firewall » that removes the semantic of XML documents to keep only their presentation. I like to think at this technique as a semantic « anti-firewall » or « tunnel » that keeps the semantic of XML documents intact until the very last stage before it hits the browser’s rendering engine…
David,
That would be with great pleasure, but I have done the silly thing to get engaged in
three books projects at the same time (believe me, that’s way too much) and I wouldn’t
be able to look at your examples in the short term!
Maybe in a few months?
Thanks,
Eric
Hey Eric,
> Thanks for the pointer!
np.
I have a BUNCH more code that I think will interest you, and while its not something that
can be used for anything beyond generating ideas (at least at this stage… still
deciding on how I plan to use it from a book perspective) you’re welcome to take a look
at it if this interests you. Let me know, and I will package up a preview for you to
take a look at. Cheers :)
Subject: Client side XSLT
Hi David,
I have been pleading for client *and* server side XSLT for more than five years (see for instance this post in French: http://xmlfr.org/listes/xml-tech/2001/11/0300.html) and I do share your enthusiasm :) …
I think that we are at a stage where we can seriously use XSLT client site and our upcoming Web 2.0 book introduces XSLT is a chapter about technologies that will likely enter into the « Web 2.0 technology stack » short term.
Thanks for the pointer!
Eric
« Pine me » = « Ping me » :D
Hi Eric,
I think maybe we should chat… :D
In short, I’ve been working on a few things that I have never released due to the fact
that they are still part of what was the Browser-based XML title for O’Reilly, and what
will more than likely be used in a combination of other book-related projects in the
near term future. Take a look at http://www.oreillynet.com/xml/blog/2006/06/opera_90_final_released.html and
access the « A + B = » in IE, Mozilla, or Safari, and then view source for a better
understanding of part of what I am refering to. There’s LOTS of stuff that can be done
that doesn’t attempt to make XSLT as the primary focus, and instead as the glue that
binds the strengths of each browser to perform a desired function using a simple,
declarative XML syntax that we both know XSLT excels at more so than anything else. Pine
me at the email posted to my O’Reilly blog (linked above) if you want a few more
details/code samples.
Gregoire: yes, that’s the kind of things I had in mind when I wrote that « there are probably a number of other (easier?) solutions for the specific problem I have solved here » :) …
Still, I think that this is an interesting technique to serve clean documents and do the remaining nasty bits under the hood just before display.
I have just a something to notice about the javascript:play() link.
I think it would be better to leave the link to the mp3 file in @href and to make a DOM script so that it handles a click event on specific links with @rel=enclosure.
In this case, you don’t have to rewrite your document with XSLT, just to add a script to handle user interactions (maybe just copy and add a script tag to the head tag)
Hey Eric,
Would you care to participate in a panel at the upcoming SXSW interactive conference in March in Austin, TX, regarding client side XSLT tricks and ideas?
ping me at lsimon at commoner dot com =)