<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jabbering Giraffe &#187; xslt</title>
	<atom:link href="http://happygiraffe.net/blog/tag/xslt/feed/" rel="self" type="application/rss+xml" />
	<link>http://happygiraffe.net/blog</link>
	<description></description>
	<lastBuildDate>Wed, 19 Oct 2011 10:40:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>Search &amp; Replace in XSLT 2</title>
		<link>http://happygiraffe.net/blog/2009/07/23/search-replace-in-xslt-2/</link>
		<comments>http://happygiraffe.net/blog/2009/07/23/search-replace-in-xslt-2/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 21:07:45 +0000</pubDate>
		<dc:creator>Dominic Mitchell</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[xslt]]></category>

		<guid isPermaLink="false">http://happygiraffe.net/blog/?p=1560</guid>
		<description><![CDATA[For a project at $WORK, we want to implement Solr&#8217;s spelling suggestions. When you ask solr to provide suggestions, it comes back with something like this (the original search was spinish englosh): &#60;response&#62; … &#60;lst name=&#34;spellcheck&#34;&#62; &#60;lst name=&#34;suggestions&#34;&#62; &#60;lst name=&#34;spinish&#34;&#62; &#8230; <a href="http://happygiraffe.net/blog/2009/07/23/search-replace-in-xslt-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For a project at $WORK, we want to implement Solr&#8217;s spelling suggestions.  When you ask solr to provide suggestions, it comes back with something like this (the original search was <em>spinish englosh</em>):</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;response<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    …
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;lst</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;spellcheck&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;lst</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;suggestions&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;lst</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;spinish&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;numFound&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;startOffset&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>19<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;endOffset&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>26<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arr</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;suggestion&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;str<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>spanish<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/str<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/arr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/lst<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;lst</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;englosh&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;numFound&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;startOffset&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>27<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;endOffset&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>34<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arr</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;suggestion&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;str<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>english<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/str<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/arr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/lst<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;lst</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;spinish&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;numFound&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;startOffset&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>60<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;int</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;endOffset&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>67<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/int<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arr</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;suggestion&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;str<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>spanish<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/str<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/arr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/lst<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        …
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/lst<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/lst<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/response<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>What we want to do is transform this into:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Did you mean <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;?q=spanish%20english&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>spanish english<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>?<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>As it turns out, this is a non-trivial task in XSLT.  It&#8217;s doable, but significantly easier in <a href="http://www.w3.org/TR/xslt20/">XSLT 2</a>, since you are less restricted by the rules on result-tree-fragments.</p>
<p>The first problem to solve is getting the data into a sensible data structure for further processing.  In a real language, I&#8217;d want a list of <code>(from, to)</code> pairs.  In XSLT, sequences are always flat.  The way to simulate this is to construct an element for the pair.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:variable</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;suggRoot&quot;</span> <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;/response/lst[@name='spellcheck']/lst[@name='suggestions']&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:variable</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;suggestions&quot;</span> <span style="color: #000066;">as</span>=<span style="color: #ff0000;">&quot;element(sugg)*&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:for-each</span> <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;distinct-values($suggRoot/lst/@name)&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #808080; font-style: italic;">&lt;!-- Pick the first suggestion for this name. --&gt;</span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sugg</span> <span style="color: #000066;">from</span>=<span style="color: #ff0000;">&quot;{.}&quot;</span> <span style="color: #000066;">to</span>=<span style="color: #ff0000;">&quot;{($suggRoot/lst[@name=current()])[1]/arr[@name='suggestion']/str[1]}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl:for-each<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl:variable<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Note the commented caveat: we always pick the first suggestion for any given name.  From my (small) experience, this isn&#8217;t an issue as the suggestions for a given word are always identical.</p>
<p>This results in <code>$suggestions</code> containing a sequence of elements looking like this.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sugg</span> <span style="color: #000066;">from</span>=<span style="color: #ff0000;">&quot;spinish&quot;</span> <span style="color: #000066;">to</span>=<span style="color: #ff0000;">&quot;spanish&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sugg</span> <span style="color: #000066;">from</span>=<span style="color: #ff0000;">&quot;englosh&quot;</span> <span style="color: #000066;">to</span>=<span style="color: #ff0000;">&quot;english&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

<p>Now one of the nice things about XSLT 2 is that you can define functions which are visible to XPath.  So we can write a fairly simple recursive function to do the search and replace.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #808080; font-style: italic;">&lt;!-- Take some input and a list of suggestions, and do a recursive search and</span>
<span style="color: #808080; font-style: italic;">       replace over the input until all have been applied. --&gt;</span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:function</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;my:replaceSuggestions&quot;</span> <span style="color: #000066;">as</span>=<span style="color: #ff0000;">&quot;xs:string&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:param</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;input&quot;</span> <span style="color: #000066;">as</span>=<span style="color: #ff0000;">&quot;xs:string&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:param</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;suggestions&quot;</span> <span style="color: #000066;">as</span>=<span style="color: #ff0000;">&quot;element(sugg)*&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:variable</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;sugg&quot;</span> <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;$suggestions[1]&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:sequence</span> <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;</span>
<span style="color: #009900;">      if (count($suggestions) &gt; 0) then</span>
<span style="color: #009900;">        my:replaceSuggestions(replace($input, $sugg/@from, $sugg/@to), $suggestions[position() &gt; 1])</span>
<span style="color: #009900;">      else</span>
<span style="color: #009900;">        $input&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl:function<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>There are a few things to note:</p>
<ul>
<li>You have to give your function a namespace prefix.</li>
<li>The <code>xsl:param</code>&#8216;s are used in order (not by name) to specify the arity of the function.</li>
<li>The <code>as</code> attributes aren&#8217;t necessary, but the idea of types in XSLT is growing on me.  I&#8217;d rather know about type problems as soon as possible.</li>
<li>The notion of <a href="http://en.wikipedia.org/wiki/CAR_and_CDR">cdr</a> (tail) in XSLT is rather odd: the sequence of all nodes in the sequence whose position is greater than one.</li>
<li>Even though I&#8217;m using <a href="http://www.w3.org/TR/xpath-functions/#func-replace"><code>replace()</code></a>, I&#8217;m not taking any precautions against escaping regex characters.  I&#8217;m certain that these won&#8217;t occur given my data.</li>
</ul>
<p>So finally, we end up with:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:variable</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;newQuery&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:value-of</span> <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;my:replaceSuggestions($input, $suggestions)&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl:variable<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;spelling&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:text<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Did you mean <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl:text<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;em<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;?q={encode-for-uri($newQuery)}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:value-of</span> <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;$newQuery&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/em<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl:text<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>?<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl:text<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>I don&#8217;t think all this will win any awards for elegance, but it does work. <img src='http://happygiraffe.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://happygiraffe.net/blog/2009/07/23/search-replace-in-xslt-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Practical Fascism</title>
		<link>http://happygiraffe.net/blog/2007/08/16/practical-fascism/</link>
		<comments>http://happygiraffe.net/blog/2007/08/16/practical-fascism/#comments</comments>
		<pubDate>Thu, 16 Aug 2007 00:33:00 +0000</pubDate>
		<dc:creator>Dominic Mitchell</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[xslt]]></category>

		<guid isPermaLink="false">http://happygiraffe.net/2007/08/16/practical-fascism/</guid>
		<description><![CDATA[On my recent project at work, I&#8217;ve instigated a number of features: An XSLT stylesheet that strips out all inline JavaScript and inline CSS before it ever hits the browser. Go-go Unobtrusive JavaScript! Lots of jUnit tests: Every piece of &#8230; <a href="http://happygiraffe.net/blog/2007/08/16/practical-fascism/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>On my recent project at work, I&#8217;ve instigated a number of features:</p>
<ul>
<li>An <span class="caps">XSLT</span> stylesheet that strips out all inline JavaScript and inline <span class="caps">CSS</span> before it ever hits the browser.  Go-go <a href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript">Unobtrusive JavaScript</a>!</li>
<li>Lots of <a href="http://junit.org/">jUnit</a> tests:
<ul>
<li>Every piece of static <span class="caps">HTML</span> gets validated via <a href="http://relaxng.org/">RelaxNG</a> (we had to use RelaxNG in order to allow mixed namespaces).</li>
<li>Ditto for every piece of <span class="caps">XSLT</span>.</li>
<li>A <a href="http://en.wikipedia.org/wiki/XML#Well-formed_and_valid_XML_documents">well-formedness</a> test for every piece of <span class="caps">XML</span>.</li>
<li>A <a href="http://www.jslint.com/">jslint</a> test to check every file of JavaScript isn&#8217;t doing anything silly.</li>
<li>A &#8220;no tabs&#8221; test to ensure that there are no literal tabs in any piece of source code (in accordance with our local conventions).</li>
</ul>
</li>
</ul>
<p>I haven&#8217;t yet gotten around to integrating <a href="http://checkstyle.sourceforge.net/">checkstyle</a>.  And I really need to write an XQuery parser that understands the ancient dialect we seem to be saddled with.</p>
<p>On the whole, these tests have proved to be a minor inconvenience up-front, often leading to groans around the office when the build breaks.  But as a whole they&#8217;ve kept the code base clean and managed to detect problems early.  So on the whole they&#8217;re a win.  I&#8217;ll definitely be dragging them along to my next project.</p>
]]></content:encoded>
			<wfw:commentRss>http://happygiraffe.net/blog/2007/08/16/practical-fascism/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Client-Side XSLT</title>
		<link>http://happygiraffe.net/blog/2006/07/31/client-side-xslt/</link>
		<comments>http://happygiraffe.net/blog/2006/07/31/client-side-xslt/#comments</comments>
		<pubDate>Mon, 31 Jul 2006 23:54:00 +0000</pubDate>
		<dc:creator>Dominic Mitchell</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[xslt]]></category>

		<guid isPermaLink="false">http://happygiraffe.net/2006/07/31/client-side-xslt/</guid>
		<description><![CDATA[I&#8217;ve been playing with XSLT in the Browser. It appears simple enough: Just add an xml-stylesheet processing instruction to the top of your XML, pointing at your XSLT. &#60;?xml-stylesheet href="stylish.xsl" type="text/xsl"?&#62; But there&#8217;s one more condition that needs to be &#8230; <a href="http://happygiraffe.net/blog/2006/07/31/client-side-xslt/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing with <span class="caps">XSLT</span> in the Browser.  It appears simple enough: Just add an xml-stylesheet processing instruction to the top of your <span class="caps">XML</span>, pointing at your <span class="caps">XSLT</span>.</p>
<pre>
  &lt;?xml-stylesheet href="stylish.xsl" type="text/xsl"?&gt;
</pre>
<p>But there&#8217;s one more condition that needs to be met: Inside the stylesheet itself, you have to say <code>&lt;xsl:output type="html"/&gt;</code>.  Not xml.  Not leaving out the xsl:output tag.  It has to be present and set to html or you don&#8217;t get any useful output.</p>
<p>My thanks to <a href="http://developer.mozilla.org/en/docs/XSLT_in_Gecko:Generating_HTML"><span class="caps">XSLT</span> in Gecko : Generating <span class="caps">HTML</span></a> on the lovely <a href="http://developer.mozilla.org/">devmo</a> for pointing out the error of my ways to me.</p>
]]></content:encoded>
			<wfw:commentRss>http://happygiraffe.net/blog/2006/07/31/client-side-xslt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XSLT Character Creation</title>
		<link>http://happygiraffe.net/blog/2006/02/03/xslt-character-creation/</link>
		<comments>http://happygiraffe.net/blog/2006/02/03/xslt-character-creation/#comments</comments>
		<pubDate>Fri, 03 Feb 2006 17:31:00 +0000</pubDate>
		<dc:creator>Dominic Mitchell</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[xslt]]></category>

		<guid isPermaLink="false">http://happygiraffe.net/2006/02/03/xslt-character-creation/</guid>
		<description><![CDATA[I&#8217;ve just spent most of the afternoon on a character building exercise. I have some XML like this: &#60;symbol unicode="2103"/&#62; And I need to turn that into the numeric character reference &#38;#x2013;. It&#8217;s perfectly possible to do so with a &#8230; <a href="http://happygiraffe.net/blog/2006/02/03/xslt-character-creation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just spent most of the afternoon on a character building exercise.  I have some <span class="caps">XML</span> like this:</p>
<pre>
  &lt;symbol unicode="2103"/&gt;
</pre>
<p>And I need to turn that into the numeric character reference <code>&amp;#x2013;</code>.  It&#8217;s perfectly possible to do so with a bit of fudging around with <code>&lt;xsl:text disable-output-escaping="yes"/&gt;</code>.  But there&#8217;s a slight caveat: You&#8217;re <em>not</em> creating a numeric character reference.  You&#8217;re just creating something that <em>looks</em> like one.  Really, it&#8217;s the characters &#8220;&#38;&#8221;, &#8221;#&#8221;, &#8220;x&#8221;, &#8220;2&#8221;, &#8220;0&#8221;, &#8220;1&#8221;, &#8220;3&#8221; and &#8221;;&#8221;.</p>
<p>Now most of the time, this doesn&#8217;t matter.  You just output <span class="caps">XML</span> that looks correct and the next parser along (probably a browser) will interpret it correctly.  But it&#8217;s sleight of hand.</p>
<p>Today, I needed to copy the text contents of a node into an attribute.  Unfortunately, that text content contained one of these symbol tags.  But because it&#8217;s only a string, <span class="caps">XSLT</span> feels (correctly) that it needs to escape the leading ampersand.  So, with this input:</p>
<pre>
  &lt;name&gt;Fred &lt;symbol unicode="2013"/&gt; Bloggs&lt;/name&gt;
</pre>
<p>I get this output:</p>
<pre>
  &lt;name attrib="Fred &amp;#x2013; Bloggs"&gt;Fred &amp;#x2013; Bloggs&lt;/name&gt;
</pre>
<p>Yes, I know that the input data is completely stupid.  I can&#8217;t help that.  Unfortunately I also have the restriction that I can&#8217;t do this in multiple passes.</p>
<p>I&#8217;ve looked at the <a href="http://www.w3.org/TR/xslt#add-func">standard <span class="caps">XSLT</span> functions</a> and the <a href="http://www.w3.org/TR/xpath#corelib">standard XPath functions</a>.   I&#8217;ve looked at the <a href="http://www.exslt.org/"><span class="caps">EXSLT</span> functions</a>.  All I want is something that works like Perl&#8217;s <a href="http://perldoc.perl.org/functions/chr.html">chr</a>.</p>
<p>I noticed that Saxon has the <a href="http://saxon.sourceforge.net/saxon6.5.5/extensions.html#saxon:entity-ref">saxon:entity-ref</a> function, but annoyingly, <a href="http://xmlsoft.org/XSLT/">libxslt</a> doesn&#8217;t support it.</p>
<p>All I really need is some way of re-invoking the <span class="caps">XML</span> parser over a string of my choosing.  That way I could just wrap the characters in an element, parse it and call <code>text()</code> to get the character I need.</p>
<p>Right now, the only way that I can see of doing this is to turn <a href="http://www.unicode.org/Public/UNIDATA/UnicodeData.txt">UnicodeData.txt</a> into one big <span class="caps">XML</span> lookup table, and lookup the numbers in that.  Bleeeaaargh.</p>
<p>Thankfully, it&#8217;s not my project and the person doing it has just hacked around this in the output layer.  But it bugs me that there&#8217;s no good way to achieve this.</p>
]]></content:encoded>
			<wfw:commentRss>http://happygiraffe.net/blog/2006/02/03/xslt-character-creation/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

