<?xml version="1.0"?>
<!--This file is part of Friend2Friend. Copyright Robin Upton 2008-2009. http://f2f.RobinUpton.com     Friend2Friend is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See  http://www.gnu.org/licenses/ -->
<!-- -->
<!-- Last modified: 2009-04-15 by Robin 										-->
<!-- v 1.0 -->
<!-- Displays XML as coloured, indented XHTML.							-->
<!-- -->
<!-- N.B. Does not work fully in Mozilla due to lack of support for the namespace axis!				-->
<!-- -->
<xsl:stylesheet version="1.0" xmlns:f2f="http://friend2friend.net/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
	<xsl:variable name="attrib" select="'red'"/>
	<xsl:variable name="element" select="'maroon'"/>
	<xsl:variable name="comment" select="'grey'"/>
	<xsl:variable name="p-i" select="'#338866'"/>
	<xsl:variable name="syntax" select="'blue'"/>
	<xsl:variable name="text" select="'black'"/>
	<xsl:variable name="tab" select="'&#160;&#160;&#160;&#160;&#160;&#160;'"/>
	<xsl:variable name="nsXML" select="'http://www.w3.org/XML/1998/namespace'"/>
	<xsl:template match="/f2f:displayreq">
		<xsl:for-each select="node()">
			<xsl:call-template name="f2f:xml2html"/>
		</xsl:for-each>
	</xsl:template>
	<xsl:template name="f2f:xml2html">
		<!-- = Whether or not to show child elements -->
		<xsl:param name="deep" select="1"/>
		<!-- = How deep we have gone (used for indenting) -->
		<xsl:param name="depth" select="0"/>
		<xsl:choose>
			<!-- Text Content -->
			<xsl:when test="self::text()">
				<font color="{$text}">
					<xsl:value-of select="."/>
				</font>
			</xsl:when>
			<!-- Comment -->
			<xsl:when test="self::comment()">
				<xsl:for-each select="ancestor::*[$depth>=position()]">
					<xsl:value-of select="$tab"/>
				</xsl:for-each>
				<font color="{$syntax}">&lt;!-- </font>
				<font color="{$comment}">
					<xsl:call-template name="insert-br">
						<xsl:with-param name="depth" select="$depth"/>
						<xsl:with-param name="text" select="."/>
					</xsl:call-template>
				</font>
				<font color="{$syntax}">--&gt;</font>
				<br/>
			</xsl:when>
			<!-- Processing Instruction -->
			<xsl:when test="self::processing-instruction()">
				<xsl:for-each select="ancestor::*[$depth>=position()]">
					<xsl:value-of select="$tab"/>
				</xsl:for-each>
				<font color="{$p-i}">&lt;? <xsl:value-of select="."/> ?&gt;</font>
				<br/>
			</xsl:when>
			<xsl:otherwise>
				<!-- Start Element -->
				<!--				check. ... truth is , IF PREVIOUS ELEMENT NOT A TEXT, THEN INDENT -->
				<xsl:if test="1">
					<xsl:call-template name="indent">
						<xsl:with-param name="depth" select="$depth"/>
					</xsl:call-template>
				</xsl:if>
				<font color="{$syntax}">&lt;</font>
				<font color="{$element}">
					<xsl:value-of select="name()"/>
				</font>
				<!-- Namespaces -->
				<!-- Works fine for XML starlet, but not supported by Firefox 3.0.x :( -->
				<xsl:for-each select="namespace::*[ . !=$nsXML]">
					<xsl:variable name="aname">
						<xsl:if test="name()=''">xmlns</xsl:if>
						<xsl:if test="name()!=''">xmlns:<xsl:value-of select="name()"/>
						</xsl:if>
					</xsl:variable>
					<xsl:call-template name="show-attr">
						<xsl:with-param name="name" select="$aname"/>
						<xsl:with-param name="value" select="."/>
					</xsl:call-template>
				</xsl:for-each>
				<!-- Attributes -->
				<xsl:for-each select="@*">
					<xsl:call-template name="show-attr">
						<xsl:with-param name="name" select="name()"/>
						<xsl:with-param name="value" select="."/>
					</xsl:call-template>
				</xsl:for-each>
				<!-- Close empty tag -->
				<xsl:if test="count(node())=0">
					<font color="{$syntax}">/</font>
				</xsl:if>
				<font color="{$syntax}">&gt;</font>
				<!-- <br/> iff (i) no descendants, or (ii) the first descendant is not a non-empty text node -->
				<xsl:if test="count(node())=0 or (generate-id(node()[1]) != generate-id(text()[normalize-space(.)!=''][1]))">
					<br/>
				</xsl:if>
				<!-- Children -->
				<xsl:if test="$deep = 1">
					<xsl:for-each select="node()">
						<xsl:call-template name="f2f:xml2html">
							<xsl:with-param name="deep" select="$deep"/>
							<xsl:with-param name="depth" select="$depth+1"/>
						</xsl:call-template>
					</xsl:for-each>
				</xsl:if>
				<xsl:if test="count(node())>0">
					<!-- Close Tags -->
					<!--						r<xsl:value-of select="generate-id(descendant::*[last()])"/>r
						t<xsl:value-of select="generate-id(descendant::text()[last()])"/>t
				<xsl:if  test="not(generate-id(descendant::*[last()]) = generate-id(descendant::text()[last()]))">	
-->
					<!-- could look more closely ... IF LAST DESCENDANT IS NOT A TEXT, THEN INDENT -->
					<xsl:if test="count(*)>0">
						<xsl:call-template name="indent">
							<xsl:with-param name="depth" select="$depth"/>
						</xsl:call-template>
					</xsl:if>
					<font color="{$syntax}">&lt;/</font>
					<font color="{$element}">
						<xsl:value-of select="name()"/>
					</font>
					<font color="{$syntax}">&gt;</font>
					<xsl:if test="count(node[text()])=0">
						<br/>
					</xsl:if>
				</xsl:if>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<xsl:template name="indent">
		<xsl:param name="depth"/>
		<xsl:for-each select="ancestor::*[$depth>=position()]">
			<xsl:value-of select="$tab"/>
		</xsl:for-each>
	</xsl:template>
	<xsl:template name="show-attr">
		<xsl:param name="name"/>
		<xsl:param name="value"/>
		<font color="{$attrib}"><xsl:value-of select="concat(' ', $name)"/></font><font color="{$syntax}">="</font><font color="{$text}"><xsl:value-of select="$value"/></font><font color="{$syntax}">"</font>
	</xsl:template>
	<!-- Replace chr(10) with <br/> -->
	<xsl:template name="insert-br">
		<xsl:param name="depth"/>
		<xsl:param name="text"/>
		<xsl:choose>
			<xsl:when test="contains($text, '&#010;')">
				<xsl:value-of select="substring-before($text, '&#010;')"/>
				<br/>
				<xsl:call-template name="indent">
					<xsl:with-param name="depth" select="$depth"/>
				</xsl:call-template>
				<xsl:call-template name="insert-br">
					<xsl:with-param name="depth" select="$depth"/>
					<xsl:with-param name="text" select="substring-after($text, '&#010;')"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$text"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
</xsl:stylesheet>

