<?xml version="1.0" encoding="iso-8859-1"?>
<!--

	digiTransformer.xsl
	part of digiTransformer,
	an XSLT Phone Number Transformation Tool
	copyright © 2004 Anton Triest [anton@cking.be]

	http://users.telenet.be/cking/webstuff/digiTransformer

	This is an XSLT solution to Zhanyong Wan's Phraser challenge,
	http://blogs.msdn.com/the1/archive/2004/03/29/102123.aspx

	created: 2004-08-05
	revised: 2004-08-18
	         2004-11-16 fixed dictionary word count

-->

<xsl:stylesheet
	version="1.0"
	xmlns="http://www.w3.org/1999/xhtml"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	>

	<!-- output to XHTML 1.0 Strict -->
	<xsl:output
		method="xml"
		version="1.0"
		encoding="iso-8859-1"
		indent="yes"
		doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
		doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
		/>

	<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
	<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
	<xsl:variable name="digit" select="'22233344455566677778889999'"/>

	<xsl:variable name="maxDigits">
		<!-- if it's provided in the input file, read it, otherwise take -1 (means no max) -->
		<xsl:choose>
			<xsl:when test="string(/digiTransformer/@maxDigits)">
				<xsl:value-of select="number(/digiTransformer/@maxDigits)"/>
			</xsl:when>
			<xsl:otherwise>-1</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	<xsl:variable name="dial" select="translate(/digiTransformer/dial/.,'-/.() ','')"/>
	<xsl:variable name="dictionary" select="document(/digiTransformer/dictionary/@href)/dictionary"/>

	<xsl:variable name="words" select="$dictionary/w[contains($dial, translate(translate(., $upper, $lower), $lower, $digit))]"/>

	<!--
		core algorithm: borrowed from DoCreatePhrases in Frans Bouma's C# program
		http://blogs.msdn.com/the1/archive/2004/04/06/108717.aspx
	-->
	<xsl:template name="collect-phrases">
		<xsl:param name="index" select="1"/>
		<xsl:param name="phrase" select="''"/>
		<xsl:param name="countDigits" select="0"/>
		<xsl:choose>
			<xsl:when test="$index &gt; string-length($dial)">
				<!-- complete phonenumber has been processed: write this phrase to the output tree -->
				<li><xsl:value-of select="$phrase"/></li>
			</xsl:when>
			<xsl:otherwise>
				<xsl:if test="$maxDigits &lt; 0 or $countDigits &lt; $maxDigits">
					<!-- simply use the digit as a 'word' in the phrase and continue with the next digit -->
					<xsl:call-template name="collect-phrases">
						<xsl:with-param name="index" select="$index + 1"/>
						<xsl:with-param name="phrase" select="concat($phrase, substring($dial, $index, 1))"/>
						<xsl:with-param name="countDigits" select="$countDigits + 1"/>
					</xsl:call-template>
				</xsl:if>
				<xsl:for-each select="$words">
					<xsl:if test="($index + string-length(.) - 1) &lt;= string-length($dial)">
						<xsl:variable name="value" select="translate(translate(., $upper, $lower), $lower, $digit)"/>
						<xsl:if test="starts-with(substring($dial, $index), $value)">
							<!-- match found: fill in word and recurse into the rest of the string -->
							<xsl:call-template name="collect-phrases">
								<xsl:with-param name="index" select="$index + string-length(.)"/>
								<xsl:with-param name="phrase" select="concat($phrase, .)"/>
								<xsl:with-param name="countDigits" select="$countDigits"/>
							</xsl:call-template>
						</xsl:if>
					</xsl:if>
				</xsl:for-each>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:template match="/digiTransformer">
		<!-- input root element: start generating xhtml output -->
		<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
			<head>
				<title>digiTransformer</title>
				<meta http-equiv="content-type" content="text/html;charset=iso-8859-1"/>
				<meta name="generator" content="digiTransformer XSLT stylesheet"/>
				<meta name="author" content="Anton Triest [anton@cking.be]"/>
				<link rel="stylesheet" type="text/css" href="digiTransformer.css"/>
			</head>
			<body>
				<h1>digiTransformer</h1>
				<p class="larger"><a href="http://users.telenet.be/cking/webstuff/digiTransformer/v1/info.html" title="more info">An XSLT Phone Number Transformation Tool</a></p>
				<p>
					This is <a href="mailto:anton@cking.be" title="anton@cking.be">my</a> solution to Zhanyong Wan's
					<a href="http://blogs.msdn.com/the1/archive/2004/03/29/102123.aspx">Phraser</a> programming challenge.
				</p>
				<h2>input</h2>
				<xsl:apply-templates select="dial"/>
				<xsl:apply-templates select="@maxDigits"/>
				<p>dictionaries (<xsl:value-of select="count($dictionary/w)"/> words)</p>
				<ul><xsl:apply-templates select="dictionary"/></ul>
				<h2>output</h2>
				<xsl:call-template name="print-words"/>
				<ul class="phrases">
					<xsl:call-template name="collect-phrases"/>
				</ul>
			</body>
		</html>
	</xsl:template>

	<xsl:template match="dial">
		<p>dial: <span class="dial"><xsl:value-of select="."/></span></p>
	</xsl:template>

	<xsl:template match="@maxDigits">
		<p>maxDigits: <b><xsl:value-of select="."/></b></p>
	</xsl:template>

	<xsl:template match="dictionary">
		<li><a href="{@href}"><xsl:value-of select="@href"/></a></li>
	</xsl:template>

	<xsl:template name="print-words">
		<p>
			subset:
			<b>
				<xsl:for-each select="$words">
					<xsl:value-of select="."/>&#160;
				</xsl:for-each>
			</b>
			(<xsl:value-of select="count($words)"/> words)
		</p>
	</xsl:template>

</xsl:stylesheet>

