Use Google as Your Gateway to the Mobile Internet

If you'd like to offer your content to mobile users in a slightly more mobile-friendly format, you don't necessarily have to redesign all your web pages. Google has released a well-hidden Google Wireless Transcoder that transforms any HTML page into WAP (WML or XHTML) format. My InformIT article Use Google as Your Gateway to the Mobile Internet describes how you can benefit from this service and how you can use it to make your content more accessible to mobile users.

Safari does not URL-encode arguments of the document() function

David Peterson has found an interesting Safari bug: it looks like most other XSLT-capable browsers automatically URL-encode the invalid strings passed to the document() function, whereas Safari uses the input argument as-is (and fails if it contains unexpected characters).

Still, don't forget that URL encoding is the programmer's job and that the browsers only fix your errors when they do the encoding behind the scenes. However, properly encoding a URL string with the limited set of string-handling functions of XSLT 1.0 is close to Mission Impossible ... although of course it's been proven that it can be done even with a Turing machine ;)

And, last but not least, if you need a more detailed description of URL encoding - here it is.

Output UTF-8 text from ASP script

I had to write an application that outputs CSV text encoded as UTF-8 from an ASP script. This is what I've ended with:
Sub OutputCSV(finalText)
  Response.Clear
  Response.Charset = "utf-8"
  Response.ContentType = "text/plain"
  Response.Codepage = 65001
  Response.Write finalText
  Response.End
End Sub
In my application, the complete CSV data was stored in the finalText variable. If that's not the case, replace the Response.Write statement with the CSV-generating logic.

Using document function with URI in XSLT

I've encountered an interesting question on an XML forum recently: “Why can't I use the document() function to download XML content from another web site?”

The reason is very simple: the document function in XSLT can be a very problematic cross-site-scripting (XSS) tool if it's allowed to download a document from any URI. Therefore it should be limited to the domain of the XSLT stylesheet calling it, similar to the restrictions imposed on the XMLHttpRequest object. Internet Explorer 7 and Firefox 2.0.0.11 enforce this restriction and Opera decided not to support the document() function even when they've finally added XSLT support (and here is an ecstatic post claiming they do it now).

Enhance Your AJAX Applications with Visual Cues

In the Enhance Your AJAX Applications with Visual Cues article published by InformIT, I'm describing various techniques you can use to help your users get the most out of your AJAX application.

Select XML elements in XSLT template

I've stumbled across a fantastic thread discussing how you can use various XSLT mechanisms (for example, xsl:apply-template with select option versus xsl:template with XPath match expression). Highly recommended reading :)

Text nodes in XSLT

It's amazing how many people have issues with whitespace handling in XSLT. I admit it's counter intuitive unless you start thinking in XML terms (remember: XSLT stylesheet is first parsed by an XML parser). The rule I'll explain today is very simple: whitespace-only text nodes from XSLT stylesheet are not copied to the output.

In the example mentioned by Alexandar …
<input type="submit">
  <xsl:attribute name="value">
    Login
  </xsl:attribute>
</input>
… a single text node within the xsl:attribute element (as parsed by XML parser) includes the Login text as well as a few whitespace characters. To get rid of the extra whitespace characters (it looks like the target application hates having leading whitespaces in submit button names), you could write the whole value in-line (now there is no extra whitespace in the attribute value):
<xsl:attribute name="value">Login</xsl:attribute>
Alternatively, you could split the contents of the xsl:attribute element into whitespace-only text nodes (which are not copied to the output) and a non-whitespace text node (containing the Login text). The easiest way to do it is to insert an xsl:text element within the xsl:attribute element:
<xsl:attribute name="value">
  <xsl:text>Login</xsl:text>
</xsl:attribute>

This post is part of You've asked for it series of articles.

Search Engine Optimization in XML+XSLT designs

It's amazing that the question “how do I perform SEO for a web site that does XSLT transformation on the browser” still pops up, as the short answer is very obviously “You can't.”The long answer is, as always, a bit more complex:
  • Google can process XML data, but only stores it into supplementary index (lower rankings)
  • If the server's XML output does not contain enough context (for example, product description in HTML-ish format), the search engines cannot make any sense out of it, so it would not be indexed appropriately.
  • Search engines will not follow explicit (let alone implicit) links in XML documents, so you need a sitemap (classic HTML page, Atom/RSS feed or Google sitemap) to help search engines find the content pages
Until Google (and other search engines) implement XSLT transformations, the only sensible approach is to detect the client capabilities on the server and perform the XSLT transformation on the server if the client cannot do it (the whole architecture is described in my InformIT article Optimized Presentation of XML Content that was published almost exactly a year ago).

Dynamic output elements in XSLT

Sometimes the output element that has to be emitted by an XSLT transformation is not known in advance. For example, using the book structure from one of the previous posts
<book title="Sample book">
  <chapter title="First chapter">
    <section title="Section in first chapter">
      <section title="Chunk of text within a section">
        <para>My paragraph</para>
      </section>
    </section>
  </chapter>
</book>
… we'd like to generate HTML H1 heading for the chapter and H2Hx headings for the sections. It's obvious that the heading element's name can be computed easily as 'H'+number-of-ancestors. The corresponding XSLT template is of course a bit more complex and uses the xsl:element tag to generate the output element.
<xsl:template match="chapter|section">
  <xsl:element name="{concat('h',count(ancestor::*))}">
    <xsl:value-of select="@title" />
  </xsl:element>
  <xsl:apply-templates />
</xsl:template>

The xsl:element expects a QName (a string specifying the element's name) as its name attribute. To insert dynamically computed element's name, you have to use curly braces around the expression.

Add a truly modal dialog box to your web application

If you do a search on "JavaScript Modal Dialog", you'll get a lot of hits and a variety of solutions … but most of them tend to forget that the browser users can use the keyboard keys as well as the mouse to navigate around the web page. The solution I'm describing in my new InformIT article Building Modal Dialogs into Your Web Application addresses both input devices, giving you a truly modal dialog box that captures all key- and mouse clicks.