Client side XSLT brings live to static HTML pages and microformats

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>        

[hatom.xhtml]

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(&#34;http://xmlfr.org/documentations/articles/i040130-0001/01%20-%20C'est%20base%20sur%20XML.mp3&#34;);"
                                    rel="enclosure">play</a>] (<span class="htype"
                              >audio/mpeg</span>, <span class="hLength">231469</span> bytes).</p>
                  </div>
            

[hatom-decorated.xhtml]

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>

            

[decorateMf.xsl]

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…

Too many SVG profiles

Our upcoming Web 2.0 book is giving me the opportunity to have a closer look to the state of SVG.

After all kind of announcements for native SVG support in browsers, I was expecting that with my new Ubuntu Dapper distribution, SVG would be really easy to display.

The first thing I have tested is to display the clock that animates the front page of XMLfr: <em> You need either a browser that supports SVG or a <a href="http://www.adobe.com/svg/viewer/install/">SVG plug-in</a> to display this image. </em> [download] in Firefox.

First test, first disappointment: the text « Réalisé en SVG » doesn’t show up in Firefox. This text is displayed on a path using a textPath element which isn’t supported by Firefox.

Beginning to wonder if all that would be as easy as I had thought, I have developed a sample document showing the relations between the tags in the RSS channel of the book site.

I wanted to show the level of animation that can be done declaratively without a single line of Javascript and I have used the « set » element.

Second test, second deception: this was just not working.

Thinking that I needed to do more exhaustive tests, I decided to install the Abode SVG plugin which, fortunately is quite easy if you switch the native SVG support in Firefox using about:config as explained on Mozillazine. A very cool feature is that you can switch between native and plug-in support trough clicking on « svg.enabled » option without having to restart the browser.

After more tests and the very helpful mouseEvents SVG sample, I came to the conclusion that no implementation, including Adobe SVG plug-in, supports the « mouseover » and « mouseout » events correctly and switched to using « mousedown » and « mouseup » instead.

The result is a SVG document which (I think) is perfectly valid but works only with the Adobe SVG plug-in:

<em> You need either a browser that supports SVG or a <a href="http://www.adobe.com/svg/viewer/install/">SVG plug-in</a> to display this image. </em>
[download]

This SVG document works fine with the Adobe plug-in but doesn’t work with any of the other implementations that I have tested. Note that it is almost working with Opera 9.0b2 but this implementation doesn’t seem to support « set » elements on groups: if I move the « set » elements to the individual shapes I can get it working with Opera.

The full test report is a below:

Test Firefox 1.5.0.4 (native mode) Adobe SVG viewer 3.01 beta 3 Opera 9.0b2 Konqueror 3.5.2 Amaya 8.5 X-smiles 1.0alpha1
SVG clock [download] No support for « textPath »: the text doesn’t show. OK OK No animation The document is reported as non well formed! No animation
Tags [download] No support for « set »: no link are displayed and nothing happens when you click on a tag. OK No support for « set »: no link are displayed and nothing happens when you click on a tag. No support for « set » not for the visibility attributes: all the links are always displayed. Furthemore, the browser crashes after a while when this document is left opened. No support for « set » not for the visibility attributes: all the links are always displayed. The « text-anchor: middle » property doesn’t work either. Crashes when there is a DOCTYPE declaration in the SVG document and throws an exception « Simple duration is not defined for this animation element » probably due to the fact that the set elements do not have durations when the DOCTYPE is removed.

Also, the media type « image/svg+xml » seems to be a problem for the Adobe plug-in in Firefox even if, curiously, this isn’t systematic.

I could probably get this sample working on most of these implementations by switching to Javascript animation and carefully testing against each of them, but is that something we really want to do again?

Wasn’t SVG supposed to be interoperable? The current situation reminds me on the contrary of the worse period of the browsers war even if I have no doubt that this time there are no political reasons behind that.

Mozilla explains that Firefox SVG is a subset of SVG 1.1, but not any of the official profiles (Tiny, Basic, Full).

Other implementations have probably similar policies and I can understand their reasons. However, I am wondering if these partial implementations do not hurt SVG more than they help.

The commonality between them is that, except Konqueror when it core dumps, they all fail silently when they encounter a feature that they do not support leaving users with the feeling that the document they are viewing is bogus.

When a user with a browser that has no support for SVG finds a SVG document, she/he is invited to load a plug-in. When her/his browser has one of these partial supports, she/he just moves away.

Web 2.0 at XML Prague

This coming week-end, I’ll have the pleasure to be at XML Prague, a small and friendly XML conference in a wonderful city.

This year, I’ll leave out my usual XML schema languages expert hat to speak on two topics:

  • An experience to define a RDF/XML Query By Example language. This presentation relates a very cool project that I am developing for one of my customers (INSEE) and that I have also presented at Extreme Markup Languages last year. It is very on topic with the focus of XML Prague this year which is « XML Native Databases and Querying XML ».
  • Web 2.0: myth and reality, a presentation derived from the blog entry with the same title. Even though people could probably argue that Web 2.0 is about making a web that can be queried, this talk will probably be felt more out of topic. I hope it will still be well received and look forward to delivering it in Prague.

XML Prague 2005 had also been an opportunity to see Prague that I hadn’t seen since… 1981… (I can tell you that so many things had changed that I could hardly recognize the city) and also to meet many members from an active and creative Eastern European XML community with whom I had often exchanged emails but had had few opportunities to meet face to face.

I have no doubt XML Prague 2006 will be as fun as its preceding issue.

Normalizing Excel’s SpreadsheetML using XSLT – Part 2

As reported by one of the comments, there was a bug in the XSLT transformation which « normalizes » Excel’s SpreadsheetML documents that I had posted in a previous post.

I have fixed this bug and the new version is:

<?xml version="1.0"?>
<!--

Adapted from http://ewbi.blogs.com/develops/2004/12/normalize_excel.html

This product may incorporate intellectual property owned by Microsoft Corporation. The terms
and conditions upon which Microsoft is licensing such intellectual property may be found at
http://msdn.microsoft.com/library/en-us/odcXMLRef/html/odcXMLRefLegalNotice.asp.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
    <xsl:output method="xml" indent="no" encoding="UTF-8"/>
    <xsl:template match="/">
        <xsl:apply-templates select="node()" mode="normalize"/>
    </xsl:template>
    <xsl:template match="@*|node()" mode="normalize">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="normalize"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="ss:Cell/@ss:Index" mode="normalize"/>
    <xsl:template match="ss:Cell" name="copy" mode="normalize">
        <xsl:copy>
            <xsl:apply-templates select="@*" mode="normalize"/>
            <xsl:variable name="prevCells" select="preceding-sibling::ss:Cell"/>
            <xsl:variable name="nbPrecedingIndexes"
                select="count(preceding-sibling::ss:Cell[@ss:Index])"/>
            <xsl:attribute name="ss:Index">
                <xsl:choose>
                    <xsl:when test="@ss:Index">
                        <xsl:value-of select="@ss:Index"/>
                    </xsl:when>
                    <xsl:when test="count($prevCells) = 0">
                        <xsl:value-of select="1"/>
                    </xsl:when>
                    <xsl:when test="$nbPrecedingIndexes > 0">
                        <xsl:variable name="precedingCellsSinceLastIndex"
                            select="preceding-sibling::ss:Cell[count(preceding-sibling::ss:Cell[@ss:Index]|self::ss:Cell[@ss:Index]) = $nbPrecedingIndexes]"/>
                        <xsl:value-of
                            select="preceding-sibling::ss:Cell[@ss:Index][1]/@ss:Index +
                            count($precedingCellsSinceLastIndex)
                            + sum($precedingCellsSinceLastIndex/@ss:MergeAcross)
                            - count ($precedingCellsSinceLastIndex[@ss:MergeAcross])"
                        />
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of
                            select="count($prevCells) + 1 +
                            sum($prevCells/@ss:MergeAcross) -count($prevCells/@ss:MergeAcross)"
                        />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <xsl:apply-templates select="node()" mode="normalize"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
            

I have also written the following set of tests (using XSLTUnit):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:exsl="http://exslt.org/common"
  extension-element-prefixes="exsl" xmlns:xsltu="http://xsltunit.org/0/"
  exclude-result-prefixes="exsl">
  <xsl:import href="excelNormalize.xsl"/>
  <xsl:import href="xsltunit.xsl"/>
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="/">
    <xsltu:tests>
      <xsltu:test id="noIndexes">
        <xsl:variable name="input">
          <ss:Row>
            <ss:Cell>A</ss:Cell>
            <ss:Cell>B</ss:Cell>
            <ss:Cell>C</ss:Cell>
            <ss:Cell>D</ss:Cell>
            <ss:Cell>E</ss:Cell>
          </ss:Row>
        </xsl:variable>
        <xsl:call-template name="xsltu:assertEqual">
          <xsl:with-param name="id">noIndexes</xsl:with-param>
          <xsl:with-param name="nodes1">
            <xsl:apply-templates select="exsl:node-set($input)/ss:Row" mode="normalize"/>
          </xsl:with-param>
          <xsl:with-param name="nodes2">
            <ss:Row>
              <ss:Cell ss:Index="1">A</ss:Cell>
              <ss:Cell ss:Index="2">B</ss:Cell>
              <ss:Cell ss:Index="3">C</ss:Cell>
              <ss:Cell ss:Index="4">D</ss:Cell>
              <ss:Cell ss:Index="5">E</ss:Cell>
            </ss:Row>
          </xsl:with-param>
        </xsl:call-template>
      </xsltu:test>
      <xsltu:test id="withIndexes">
        <xsl:variable name="input">
          <ss:Row>
            <ss:Cell ss:Index="1">A</ss:Cell>
            <ss:Cell ss:Index="2">B</ss:Cell>
            <ss:Cell ss:Index="3">C</ss:Cell>
            <ss:Cell ss:Index="4">D</ss:Cell>
            <ss:Cell ss:Index="5">E</ss:Cell>
          </ss:Row>
        </xsl:variable>
        <xsl:call-template name="xsltu:assertEqual">
          <xsl:with-param name="id">withIndexes</xsl:with-param>
          <xsl:with-param name="nodes1">
            <xsl:apply-templates select="exsl:node-set($input)/ss:Row" mode="normalize"/>
          </xsl:with-param>
          <xsl:with-param name="nodes2" select="$input"/>
        </xsl:call-template>
      </xsltu:test>
      <xsltu:test id="firstIndex">
        <xsl:variable name="input">
          <ss:Row>
            <ss:Cell ss:Index="5">A</ss:Cell>
            <ss:Cell>B</ss:Cell>
            <ss:Cell>C</ss:Cell>
            <ss:Cell>D</ss:Cell>
            <ss:Cell>E</ss:Cell>
          </ss:Row>
        </xsl:variable>
        <xsl:call-template name="xsltu:assertEqual">
          <xsl:with-param name="id">firstIndex</xsl:with-param>
          <xsl:with-param name="nodes1">
            <xsl:apply-templates select="exsl:node-set($input)/ss:Row" mode="normalize"/>
          </xsl:with-param>
          <xsl:with-param name="nodes2">
            <ss:Row>
              <ss:Cell ss:Index="5">A</ss:Cell>
              <ss:Cell ss:Index="6">B</ss:Cell>
              <ss:Cell ss:Index="7">C</ss:Cell>
              <ss:Cell ss:Index="8">D</ss:Cell>
              <ss:Cell ss:Index="9">E</ss:Cell>
            </ss:Row>
          </xsl:with-param>
        </xsl:call-template>
      </xsltu:test>
      <xsltu:test id="altIndexes">
        <xsl:variable name="input">
          <ss:Row>
            <ss:Cell ss:Index="2">A</ss:Cell>
            <ss:Cell>B</ss:Cell>
            <ss:Cell ss:Index="5">C</ss:Cell>
            <ss:Cell>D</ss:Cell>
            <ss:Cell>E</ss:Cell>
          </ss:Row>
        </xsl:variable>
        <xsl:call-template name="xsltu:assertEqual">
          <xsl:with-param name="id">altIndexes</xsl:with-param>
          <xsl:with-param name="nodes1">
            <xsl:apply-templates select="exsl:node-set($input)/ss:Row" mode="normalize"/>
          </xsl:with-param>
          <xsl:with-param name="nodes2">
            <ss:Row>
              <ss:Cell ss:Index="2">A</ss:Cell>
              <ss:Cell ss:Index="3">B</ss:Cell>
              <ss:Cell ss:Index="5">C</ss:Cell>
              <ss:Cell ss:Index="6">D</ss:Cell>
              <ss:Cell ss:Index="7">E</ss:Cell>
            </ss:Row>
          </xsl:with-param>
        </xsl:call-template>
      </xsltu:test>
      <xsltu:test id="noIndexesMergeAcross">
        <xsl:variable name="input">
          <ss:Row>
            <ss:Cell>A</ss:Cell>
            <ss:Cell ss:MergeAcross="2">B</ss:Cell>
            <ss:Cell>C</ss:Cell>
            <ss:Cell ss:MergeAcross="3">D</ss:Cell>
            <ss:Cell>E</ss:Cell>
          </ss:Row>
        </xsl:variable>
        <xsl:call-template name="xsltu:assertEqual">
          <xsl:with-param name="id">noIndexesMergeAcross</xsl:with-param>
          <xsl:with-param name="nodes1">
            <xsl:apply-templates select="exsl:node-set($input)/ss:Row" mode="normalize"/>
          </xsl:with-param>
          <xsl:with-param name="nodes2">
            <ss:Row>
              <ss:Cell ss:Index="1">A</ss:Cell>
              <ss:Cell ss:MergeAcross="2" ss:Index="2">B</ss:Cell>
              <ss:Cell ss:Index="4">C</ss:Cell>
              <ss:Cell ss:MergeAcross="3" ss:Index="5">D</ss:Cell>
              <ss:Cell ss:Index="8">E</ss:Cell>
            </ss:Row>
          </xsl:with-param>
        </xsl:call-template>
      </xsltu:test>
      <xsltu:test id="withIndexesMergeAcross">
        <xsl:variable name="input">
          <ss:Row>
            <ss:Cell ss:Index="5" ss:MergeAcross="2">A</ss:Cell>
            <ss:Cell>B</ss:Cell>
            <ss:Cell ss:Index="10">C</ss:Cell>
            <ss:Cell ss:MergeAcross="3">D</ss:Cell>
            <ss:Cell>E</ss:Cell>
          </ss:Row>
        </xsl:variable>
        <xsl:call-template name="xsltu:assertEqual">
          <xsl:with-param name="id">withIndexesMergeAcross</xsl:with-param>
          <xsl:with-param name="nodes1">
            <xsl:apply-templates select="exsl:node-set($input)/ss:Row" mode="normalize"/>
          </xsl:with-param>
          <xsl:with-param name="nodes2">
            <ss:Row>
              <ss:Cell ss:Index="5" ss:MergeAcross="2">A</ss:Cell>
              <ss:Cell ss:Index="7">B</ss:Cell>
              <ss:Cell ss:Index="10">C</ss:Cell>
              <ss:Cell ss:MergeAcross="3" ss:Index="11">D</ss:Cell>
              <ss:Cell ss:Index="14">E</ss:Cell>
            </ss:Row>
          </xsl:with-param>
        </xsl:call-template>
      </xsltu:test>
    </xsltu:tests>
  </xsl:template>
</xsl:stylesheet>
            

These tests should help to understand what this transformation is doing.

Thanks continue to report bugs and feature requests as comments.

The influence of microformats on style-free stylesheets

It’s been a while, almost six years, since I have written my Style-free XSLT Style Sheets piece for XML.com but this simple technique remains one of my favorite.

It has not only been my first article published on XML.com but also the subject of my first talk in an IDEAlliance XML conference and it’s fair to say that it as been instrumental to launch my career of « international XML guru ».

Despite all that, this technique remains my favorite because for its efficiency. I am using it over and over. To generate (X)HTML but also many other XML vocabularies. I have been using it to generate vocabularies as different as OpenOffice documents and W3C XML Schemas. The more complex is the vocabulary to generate, the more reasons you have to keep it outside your XSLT transformations and the more efficient style-free stylesheets are.

Style-free stylesheets have become a reflex for me and that’s without even thinking about them that I have written a style-free stylesheet to power the web site of our upcoming Web 2.0 book.

In my antique XML.com paper, I had been using specific, non XHTML elements:

        <td width="75%" bgcolor="Aqua">
            <insert-body/>
        </td>

That’s working fine, but your layout documents are no longer valid XHTML and they don’t display like target documents in a browser.

Why not follow the microformats approach and use regular XHTML elements with specif class attribues instead:

        <div id="planet">
            <h1>Planet Web 2.0 the book</h1>
            <p>Aggregated content relevant to this book.</p>
            <div class="fromRss"/>
             .../...
        </div>           

In this case, the XSLT transformation replaces the content of any element with a class attribute containing the token « fromRSS » by the formated output of the RSS feed. This has the additional benefit that I can leave mock-up content to make the layout look like a final document:

<div id="planet">
            <h1>Planet Web 2.0 the book</h1>
            <p>Aggregated content relevant to this book.</p>
            <div class="fromRss">
                <ul>
                    <li>
                        <div>
                            <h2>
                                <a
                                    href="http://www.orbeon.com/blog/2006/06/02/about-json-and-poor-marketing-strategies/"
                                    title="XForms Everywhere » About JSON and poor marketing strategies"
                                    >XForms Everywhere » About JSON and poor marketing
                                strategies</a>
                            </h2>
                        </div>
                    </li>
                </ul>
            </div>
            <p>
                <a href="http://del.icio.us/rss/tag/web2.0thebook" title="RSS feed (on del.icio.us)">
                    <img src="feed-icon-24x24.png" alt="RSS feed"/>
                </a> (on <a href="http://del.icio.us/" title="del.icio.us">del.icio.us</a>)</p>
        </div>

What I like with simple ideas is that they always leave room for reuse and improvements (complex ideas on the other hand seem to only leave room for more complexity).

Web 2.0 the book

One of the reasons I have been too busy to blog these days is the project to write a comprehensive book about Web 2.0 technologies.

If Web 2.0 is about using the web as a platform, this platform is far from being homogeneous. On the contrary, it is made of a number of very different pieces of technology, from CSS to web server configuration through XML, Javascript, server side programming, HTML, …

I believe that integrating these technologies is one of the main challenges of Web 2.0 developers and I am always surprised if not frightened to see that people tend to get more and more specialized. Too many CSS gurus do not know the first thing about XML, too many XML gurus don’t know how to spell HTTP, too many Java programmers don’t want to know Javascript. And, no, knowing everything about Ajax isn’t enough to write a Web 2.0 application.

To the defense of these hyper-specialists, I have also found that most of the available resources, both online and in print, are even more heavily specialized than their authors and that even if you could read a book on each of these technologies you’d find it difficult to get the big picture and understand how they can be used together.

The goal of this book is fill the gap and be a useful resource for all the Web 2.0 developers who do not want to stay in their highly specialized domain as well as for project managers who need to grasp the Web 2.0 big picture.

This is an ambitious project on which I have started to work in December 2005.

The first phase has been to define the book outline with the helpful contribution of many friends.

The second one has been to find an editor. O’Reilly who is the editor of my two previous books happens to be also one of the co-inventors of the term « Web 2.0 » and that makes them very nervous about Web 2.0 book projects.

Jim Minatel from Wiley has immediately been convinced by the outline and the book will be published in the Wrox Professional Series.

I had initially planned to write the book all by myself but it would have taken me at least one year to complete this work and Jim wasn’t appealed by the idea of waiting until 2007 to get this book in print.

The third step has been to find the team to write the book and the lucky authors are:

Micah Dubinko is tech editing the book and Sara Shlaer is our Development Editor.

We had then to split the work between authors. The exercise has been easier than expected. Being in a position to arbiter the choice, I have found it fair to pick the chapters left by other authors and this leaves me with chapters that will require a lot of researches for me. This is fine since I like learning new things when I write but this also means more hard work.

This is my first co-authored book and I think that one of the challenges of these books is to keep the whole content coherent. This is especially true for a book which goal is to give « the big picture » and to explain how different technologies play together.

To facilitate the communication between authors, I have set up a series of internal resources (wiki, mailing list, subversion repository). It’s still too early to say if that will really help but the first results are encouraging.

More recently, I have also set up a public site (http://web2.0thebook.org/) that presents the book and aggregates relevant content. I hope that all these resources will help us to feel and act as a team rather than a set of individual authors.

The « real » work has finally started and we have now the first versions of our first chapters progressing within the Wiley review system.

It’s interesting to see the differences between processes and rules from different editors. To me, a book was a book and I hadn’t anticipated so many differences not only in the tools being used but also in style guidelines.

The first chapter I have written is about Web Services and that’s been a good opportunity to revisit the analysis I had done in 2004 for the ZDNet Web Services Convention [papers (in French)].

From a Web 2.0 developer perspective, I think that the main point is to publish Web Services that are perfectly integrated in the Web architecture and that means being as RESTfull as possible.

I have been happy to see that WSDL 2.0 appears to be making some progress in its support of REST Services even though it’s still not perfect yet. I have posted a mail with some of my findings to the Web Services Description Working Group comment list and they have split these comments as three issues on their official issue list ([CR052] [CR053] [CR054]).

I wish they can take these issues into account, even if that means updating my chapter!

Some resources I have found most helpful while I was writing this chapter are:

It’s been fun so far and I look forward to seeing this book « for real ».