XMPP PubSub + XSLT

One of the niftier configuration items for a XMPP PubSub node (see Configuring a Node) is the ability to define an XSL template to allow the PubSub component to generate a message body to go along with the message payload – basically a human readable version of the payload.

This is great because it allows you to have a single node service both bots and people. Without this you would have to define proxy bots that are subscribed to nodes and then they would send out chat messages for each incoming PubSub event for people in their roster.

Not exactly a friendly model IMO.

So to prepare for this I started working on a XSLT file to transform an Atom payload to HTML – but first I needed to either learn XSLT real fast or “borrow” from someone :)…

After about an hour of googling I finally found one that a) worked and b) targeted the 1.0 version of Atom at the OpenSearch site – wow was that a gold-plated, kitchen-sink-included version! It handles Atom, RSS (all of them), RDF and some others – and after a rather great question from @metajack (aka Jack Moffitt):

Why bother with RSS at all?

I started pulling out all of the non-Atom bits. He also helped me grok a template scope problem that was leading me to curse XPath royally – thanks Jack!

So after many, many rounds of edit/test/curse I boiled it down to a basic template (tho I did keep some of their snazzy person and url templates – *very* nice!) and then proceeded to tweak the HTML it generates.

So if you pass in this Atom payload:

<entry xmlns=“http://www.w3.org/2005/Atom”>
    <title type=“html”>Test Atom</title>
    <link href=“http://seesmic.com/videos/FOO”/>
    <id>http://seesmic.com/videos/FOO</id>
    <author>
        <uri>http://seesmic.com/foobarbaz</uri>
    </author>
    <published>2009-01-03T20:46:19+00:00</published>
    <updated>2009-01-03T20:46:19+00:00</updated>
    <link href=“http://t.seesmic.com/thumbnail/FOO_th1.jpg” type=“image/jpeg” rel=“enclosure” title=“Test Atom”/>
    <link href=“http://v.seesmic.com/flv/FOO.flv” type=“video/x-flv” rel=“enclosure” title=“Test Atom”/>
    <source>
        <generator>SeesmicBot</generator>
        <id>http://feeds.seesmic.com/user.foobarbaz.atom</id>
        <updated>2009-01-03T20:46:19+00:00</updated>
        <title type=“html”>Test Atom</title>
        <rights>Creative Commons Attribution</rights>
    </source>
    <in-reply-to xmlns=“http://purl.org/syndication/thread/1.0” type=“application/xhtml+xml” href=“http://seesmic.com/video/FOO” ref=“FOO”/>
    <category term=“en”/>
    <rights>Creative Commons Attribution</rights>
    <link href=“http://creativecommons.org/licenses/by/3.0//us/rdf” type=“application/rdf+xml” rel=“license”/>
</entry>

You will get this:

<html xmlns=“http://www.w3.org/1999/xhtml” xmlns:xhtml=“http://www.w3.org/1999/xhtml”>
<body>
    <div>
        <a href=“http://seesmic.com/videos/FOO”><div class=“x-escape”>Test Atom</div></a> by
        <a href=“http://seesmic.com/foobarbaz”>http://seesmic.com/foobarbaz</a>;
        <p>categories: en; </p>
        <p><a href=“http://t.seesmic.com/thumbnail/FOO_th1.jpg”>Test Atom</a> (image/jpeg)</p>
        <p><a href=“http://v.seesmic.com/flv/FOO.flv”>Test Atom</a> (video/x-flv)</p>
        <p><a href=“http://creativecommons.org/licenses/by/3.0//us/rdf”>Creative Commons Attribution</a>
        </p>
    </div>
</body>
</html>

Right now we think there is a bug in how Tigase handles this (well, actually since it’s not generating the body there is a bug *somewhere*), so I can’t show you a live example :( but as soon as the dev guys fix it, or tell me what I did wrong, I’ll make another post.

You can find the XSL template I’m using here

Update: sure enough, Bart demostrated it working on his test server so I dug deeper and discovered that the Java XSLT processor is *much* more pickier than xsltproc about errors. One of the helper templates was missing but it was never called so xsltproc just gleefully went on it’s merry way where as Java’s tossed an error and just refused to do anything more. So now Tigase is generating <body></body> *and* <event><event> payload data!


 
 
 
  • crisfrankel
    Great post. What's the difference btwen ATOM and RSS 2.0?
    http://www.frankelcoachinggroup.com
  • Both Atom and RSS 2.0 are xml, so you can use this script as a start for RSS 2.0 - but the structure and content would be different. See http://www.rssboard.org/rss-specification for what goes into RSS 2.0 content.
  • Hi,
    Thanks for sharing the code................ : )
  • The implementation of pubsub#dataform_xslt is awesome ! :)
    Gotta have look at Tigase.
  • Just a heads up in case you're testing with a client that throws away pubsub messages...

    I've had trouble with pubsub messages in Adium where even though the XML console shows that the message was received, the body doesn't get displayed as a regular chat message. I'm pretty sure it's the same as this issue http://trac.adiumx.com/ticket/9146 and it's worth noting I have no such problems when testing with Psi or Spark, which both show the message body as expected.
  • That is the exact type of problem we are trying to avoid by offering a "true" body option with our PubSub events - to allow people who are consuming them who are using clients which ignore non-chat messages to having something to view.

    Like all things feature-rich, just have to get all our pieces in place and pointing at the same place :)

    thanks!
  • bmalkow
    It works for me (see below). But (maybe it is wrong) in Your xslt You should generate "<body/>" because Tigase put transformation result as child of <message/>, not <message><body/> . In this solution You can also generate <subject/> or xml:lang in <body/>.


    <iq type='set'
    to='pubsub.sphere'
    id='pub1'>
    <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
    <item id='1232'>
    <entry xmlns='http://www.w3.org/2005/Atom'>
    <title>Soliloquy</title>
    <summary>
    To be, or not to be: that is the question:
    Whether 'tis nobler in the mind to suffer
    The slings and arrows of outrageous fortune,
    Or to take arms against a sea of troubles,
    And by opposing end them?
    </summary>
    <link rel='alternate' type='text/html'
    href='http://denmark.lit/2003/12/13/atom03'/>
    <id>tag:denmark.lit,2003:entry-32397</id>
    <published>2003-12-13T18:30:02Z</published>
    <updated>2003-12-13T18:30:02Z</updated>
    </entry>
    </item>
    </publish>
    </pubsub>
    </iq>


    <iq from="pubsub.sphere" type="result" id="pub1" to="alice@sphere/sphere" />


    <message from="pubsub.sphere" id="2" to="alice@sphere" >
    <html xmlns="http://www.w3.org/1999/xhtml">
    <body>
    <div>
    Soliloquy


    To be, or not to be: that is the question:
    Whether 'tis nobler in the mind to suffer
    The slings and arrows of outrageous fortune,
    Or to take arms against a sea of troubles,
    And by opposing end them?


    </div>
    </body>
    </html>
    <event xmlns="http://jabber.org/protocol/pubsub#event">
    <items node="princely_musings" >
    <item id="1232" >
    <entry xmlns="http://www.w3.org/2005/Atom">
    <title>Soliloquy</title>
    <summary>
    To be, or not to be: that is the question:
    Whether 'tis nobler in the mind to suffer
    The slings and arrows of outrageous fortune,
    Or to take arms against a sea of troubles,
    And by opposing end them?
    </summary>
    <link rel="alternate" href="http://denmark.lit/2003/12/13/atom03" type="text/html" />
    <id>tag:denmark.lit,2003:entry-32397</id>
    <published>2003-12-13T18:30:02Z</published>
    <updated>2003-12-13T18:30:02Z</updated>
    </entry>
    </item>
    </items>
    </event>
    </message>
blog comments powered by Disqus

Creative Commons Attribution-ShareAlike 3.0 United States
This work by Mike Taylor is licensed under a Creative Commons Attribution-ShareAlike 3.0 United States.