<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tm="http://www.w3.org/2006/02/wsdl/TestMetadata" exclude-result-prefixes="tm">
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
	<!--
		Stylesheet to compare two WSDL Component Model serialization format (wsdlxml) documents

		Created: March 27, 2006, Jonathan Marsh, Microsoft.  jmarsh@microsoft.com
	-->
	<xsl:param name="implementation" />
	<xsl:variable name="aspirant-name" select="concat($implementation,'/',substring-before(filename,'.wsdl'),'.canonical.wsdlcm')"/>
	<xsl:variable name="archetype-name" select="concat('Baseline/',substring-before(filename,'.wsdl'),'.canonical.wsdlcm')"/>
	<xsl:variable name="aspirant-node" select="document($aspirant-name)"/>
	<xsl:variable name="archetype-node" select="document($archetype-name)"/>
	<xsl:variable name="supported-extensions" select="document('implementations.xml')/implementations/implementation[@results-folder=$implementation]/supports"/>
	<xsl:template match="/">
		<xsl:processing-instruction name="xml-stylesheet">type="text/xsl" href="../../results.xsl"</xsl:processing-instruction>
		<comparing aspirant="../../{$aspirant-name}" archetype="../../{$archetype-name}" source="../../../documents/good/{filename}"
			test-metadata="{concat('../../../documents/good/',substring-before(filename,'/'),'/TestMetadata.xml')}">
			<xsl:variable name="test-metadata" select="document(concat('../documents/good/',substring-before(filename,'/'),'/TestMetadata.xml'))"/>
			<xsl:variable name="required-extensions" select="$test-metadata/tm:TestMetadata/tm:Inputs/tm:Input[@role='required-extension']"/>
			<xsl:attribute name="required-extensions">true</xsl:attribute>	
			<xsl:for-each select="$required-extensions">
				<xsl:if test="not(. = $supported-extensions/@extension)">
					<xsl:attribute name="required-extensions">false</xsl:attribute>
				</xsl:if>
			</xsl:for-each>
			<xsl:if test="not($aspirant-node)"><no-aspirant>No results found for this test</no-aspirant></xsl:if>
			<xsl:if test="not($archetype-node)"><no-archetype>Baseline document missing</no-archetype></xsl:if>
			<xsl:if test="$aspirant-node and $archetype-node">
				<xsl:call-template name="compare">
					<xsl:with-param name="asp" select="$aspirant-node/*"/>
					<xsl:with-param name="arc" select="$archetype-node/*"/>
				</xsl:call-template>
			</xsl:if>
		</comparing>		
	</xsl:template>
	<xsl:template name="compare">
		<xsl:param name="asp"/>
		<xsl:param name="arc"/>
		<xsl:if test="count($asp) + count($arc) != 0">
			<xsl:choose>
				<xsl:when test="count($asp) = 0">
					<failure>
						<xsl:attribute name="xpath"><xsl:apply-templates mode="xpath" select="$arc"/></xsl:attribute>
						<xsl:call-template name="nearest-id"/>
						<p>Missing element "<xsl:value-of select="local-name($arc)"/>" in namespace "<xsl:value-of select="namespace-uri($arc)"/>".</p>
					</failure>
				</xsl:when>
				<xsl:when test="local-name($asp) != local-name($arc) or namespace-uri($asp) != namespace-uri($arc)">
					<failure>
						<xsl:attribute name="xpath"><xsl:apply-templates mode="xpath" select="$asp"/></xsl:attribute>
						<xsl:call-template name="nearest-id"/>
						<p>Expected element "<xsl:value-of select="local-name($arc)"/>" in namespace "<xsl:value-of select="namespace-uri($arc)"/>", found element "<xsl:value-of select="local-name($asp)"/>" in namespace "<xsl:value-of select="namespace-uri($asp)"/>".</p>
					</failure>
				</xsl:when>
				<xsl:otherwise>
					<!-- compare attributes -->
					<xsl:if test="count($asp/@*) != count($arc/@*)">
						<failure>
							<xsl:attribute name="xpath"><xsl:apply-templates mode="xpath" select="$asp"/></xsl:attribute>
							<xsl:call-template name="nearest-id"/>
							<p>Different number of attributes (Expected <xsl:value-of select="count($arc/@*)"/> found <xsl:value-of select="count($asp/@*)"/>).</p>
						</failure>
					</xsl:if>
					<xsl:for-each select="$arc/@*">
						<xsl:variable name="asp-att" select="$asp/@*[local-name(.)=local-name(current()) and namespace-uri(.)=namespace-uri(current())]"/>
						<xsl:if test="not($asp-att)">
							<failure>
								<xsl:attribute name="xpath"><xsl:apply-templates mode="xpath" select="$asp"/></xsl:attribute>
								<xsl:call-template name="nearest-id"/>
								<p>Attribute "<xsl:value-of select="name(.)"/>" not found.
								Closest element: <xsl:value-of select="ancestor::*[@xml:id][1]/@xml:id"/>.</p>
							</failure>
						</xsl:if>
						<xsl:if test=". != $asp-att">
							<failure>
								<xsl:attribute name="xpath"><xsl:apply-templates mode="xpath" select="$asp"/></xsl:attribute>
								<xsl:call-template name="nearest-id"/>
								<p>Attribute "<xsl:value-of select="name(.)"/>" value mismatch (found "<xsl:value-of select="$asp-att"/>", expected "<xsl:value-of select="."/>").
								Closest element: <xsl:value-of select="ancestor::*[@xml:id][1]/@xml:id"/>.</p>
							</failure>
						</xsl:if>
					</xsl:for-each>
					<!-- compare values -->
					<xsl:if test="text() and not(*)">
						<xsl:if test="$asp/text() != $arc/text()">
							<failure>
								<xsl:attribute name="xpath"><xsl:apply-templates mode="xpath" select="$asp"/></xsl:attribute>
								<xsl:call-template name="nearest-id"/>
								<p>Element "<xsl:value-of select="name(.)"/>" value mismatch (found "<xsl:value-of select="$asp/text()"/>", expected "<xsl:value-of select="$arc/text()"/>").</p>
							</failure>
						</xsl:if>
					</xsl:if>
					<!-- compare children -->
					<xsl:if test="count($asp/*) != count($arc/*)">
						<failure>
							<xsl:attribute name="xpath"><xsl:apply-templates mode="xpath" select="$asp"/></xsl:attribute>
							<xsl:call-template name="nearest-id"/>
							<p>Different number of children (Expected <xsl:value-of select="count($arc/*)"/> found <xsl:value-of select="count($asp/*)"/>).</p>
						</failure>
					</xsl:if>
					<xsl:for-each select="$arc/*">
						<xsl:variable name="p" select="position()"/>
						<xsl:call-template name="compare">
							<xsl:with-param name="asp" select="$asp/*[position()=$p]"/>
							<xsl:with-param name="arc" select="."/>
						</xsl:call-template>
					</xsl:for-each>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
	</xsl:template>
	<xsl:template match="*" mode="xpath">
		<xsl:apply-templates select="parent::*" mode="xpath"/>/<xsl:value-of select="name(.)"/>
	</xsl:template>
	<xsl:template match="@*" mode="xpath">
		<xsl:apply-templates select="parent::*" mode="xpath"/>/@<xsl:value-of select="name(.)"/>
	</xsl:template>
	<xsl:template name="nearest-id">
		<xsl:attribute name="nearest-id">
	 		<xsl:value-of select="ancestor-or-self::*[@xml:id][1]/@xml:id"/>
		</xsl:attribute>
	</xsl:template>
</xsl:stylesheet>
