<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns:wsdlcm="http://www.w3.org/2002/ws/desc/wsdl/component"
	xmlns:base="http://www.w3.org/2002/ws/desc/wsdl/component-base"
	xmlns:httpcm="http://www.w3.org/2002/ws/desc/wsdl/component-http"
	xmlns:soapcm="http://www.w3.org/2002/ws/desc/wsdl/component-soap">
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>
	
	<!--
		Stylesheet to canonicalize the WSDL Component Model Interchange format (wsdlcm)
			- sorts repeated elements in a canonical way, as deliniated at
              http://lists.w3.org/Archives/Public/www-ws-desc/2006Apr/0016.html
		Created: March 27, 2006, Jonathan Marsh, Microsoft.  jmarsh@microsoft.com
	-->

	<!-- identity transform -->
	<xsl:template match="*[not(node())]">
		<!-- prevent unwanted whitespace from distracting human readers ;-) -->
		<xsl:copy><xsl:apply-templates select="@*"/></xsl:copy>
	</xsl:template>
	<xsl:template match="*">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates/>
		</xsl:copy>
	</xsl:template>
	<xsl:template match="@*">
		<xsl:copy-of select="."/>
	</xsl:template>
	<xsl:template match="comment()">
		<xsl:copy-of select="."/>
	</xsl:template>
	
	<!-- rules to order children of particular WSDL elements -->
	
	<!--
	1.  Description.{interfaces} - sort by Interface.{name} 
	2.  Description.{bindings} - sort by Binding.{name} 
	3.  Description.{services} - sort by Service.{name} 
	4.  Description.{elementDeclarations} - sort by ElementDeclaration.{name} 
	5.  Description.{typeDefinitions} - sort by TypeDefinition.{name} 
	7.  Interface.{interfaceFaults} - sort by InterfaceFault.{name} 
	8.  Interface.{interfaceOperations} - sort by InterfaceOperation.{name} 
	-->
	<xsl:template match="wsdlcm:interfaces | wsdlcm:bindings | wsdlcm:services | wsdlcm:elementDeclarations | wsdlcm:typeDefinitions | wsdlcm:interfaceFaults | wsdlcm:interfaceOperations">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="wsdlcm:name/base:namespaceName"/>
				<xsl:sort select="wsdlcm:name/base:localName"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!--
	6.  Interface.{extendedInterfaces} - sort by Interface.{name} 
	-->
	<xsl:template match="wsdlcm:extendedInterfaces">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="//wsdlcm:interfaceComponent[@xml:id=current()/@ref]/wsdlcm:name/base:namespaceName"/>
				<xsl:sort select="//wsdlcm:interfaceComponent[@xml:id=current()/@ref]/wsdlcm:name/base:localName"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!--
	9. InterfaceOperation.{interfaceMessageReferences} - sort by InterfaceMessageReference.{message label} 
	-->
	<xsl:template match="wsdlcm:interfaceMessageReferences">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="wsdlcm:messageLabel"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!-- 
	10. InterfaceOperation.{interfaceFaultReferences} - sort by InterfaceFaultReference.{interface fault}.{name}, then by InterfaceFaultReference.{message label} 
	-->
	
	<xsl:template match="wsdlcm:interfaceFaultReferences">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="//wsdlcm:interfaceFaultComponent[@xml:id=current()/wsdlcm:interfaceFault/@ref]/wsdlcm:name/base:namespaceName"/>
				<xsl:sort select="//wsdlcm:interfaceFaultComponent[@xml:id=current()/wsdlcm:interfaceFault/@ref]/wsdlcm:name/base:localName"/>
				<xsl:sort select="wsdlcm:messageLabel"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!--
	11. Binding.{bindingFaults} - sort by BindingFault.{interfaceFault}.{name} 
	-->
	
	<xsl:template match="wsdlcm:bindingFaults">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="//wsdlcm:interfaceFaultComponent[@xml:id=current()/wsdlcm:interfaceFault/@ref]/wsdlcm:name/base:namespaceName"/>
				<xsl:sort select="//wsdlcm:interfaceFaultComponent[@xml:id=current()/wsdlcm:interfaceFault/@ref]/wsdlcm:name/base:localName"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!--
	12. Binding.{operations} - sort by BindingOperation.{interfaceOperation}.{name} 
	-->
	
	<xsl:template match="wsdlcm:bindingOperations">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="//wsdlcm:interfaceOperationComponent[@xml:id=current()/wsdlcm:interfaceOperation/@ref]/wsdlcm:name/base:namespaceName"/>
				<xsl:sort select="//wsdlcm:interfaceOperationComponent[@xml:id=current()/wsdlcm:interfaceOperation/@ref]/wsdlcm:name/base:localName"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!--
	13. BindingOperation.{bindingMessageReferences} - sort by BindingMessageReference.{interface message reference}.{name} 
	-->
	
	<xsl:template match="wsdlcm:bindingMessageReferences">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="//wsdlcm:interfaceMessageReferenceComponent[@xml:id=current()/wsdlcm:interfaceMessageReference/@ref]/wsdlcm:name/base:namespaceName"/>
				<xsl:sort select="//wsdlcm:interfaceMessageReferenceComponent[@xml:id=current()/wsdlcm:interfaceMessageReference/@ref]/wsdlcm:name/base:localName"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!--
	14. BindingOperation.{bindingFaultReferences} - sort by BindingFaultReference.{interface fault reference}.{interface fault}.{name}, then by BindingFaultReference.{interface fault reference}.{message label} 
	-->
	
	<xsl:template match="wsdlcm:bindingFaultReferences">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="//wsdlcm:interfaceFaultComponent[@xml:id=//wsdlcm:interfaceFaultReferenceComponent[@xml:id=current()/wsdlcm:interfaceFaultReference/@ref]/wsdlcm:interfaceFault/@ref]/wsdlcm:name/base:namespaceName"/>
				<xsl:sort select="//wsdlcm:interfaceFaultComponent[@xml:id=//wsdlcm:interfaceFaultReferenceComponent[@xml:id=current()/wsdlcm:interfaceFaultReference/@ref]/wsdlcm:interfaceFault/@ref]/wsdlcm:name/base:localName"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!--
	15. Service.{endpoints} - sort by Endpoint.{name} 
	-->
	<xsl:template match="wsdlcm:endpoints">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="wsdlcm:name"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<!--  Style URIs -->
	<xsl:template match="wsdlcm:style">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="wsdlcm:uri"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="soapcm:soapHeaders">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="//wsdlcm:elementDeclarationComponent[@xml:id=current()/soapcm:soapHeaderBlock/soapcm:elementDeclaration/@ref]/wsdlcm:name/base:namespaceName"/>
				<xsl:sort select="//wsdlcm:elementDeclarationComponent[@xml:id=current()/soapcm:soapHeaderBlock/soapcm:elementDeclaration/@ref]/wsdlcm:name/base:localName"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="soapcm:soapModules">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="soapcm:soapModule/soapcm:ref"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="httpcm:httpHeaders">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="*">
				<xsl:sort select="httpcm:httpHeaderComponent/httpcm:name"/>
			</xsl:apply-templates>
		</xsl:copy>
	</xsl:template>
</xsl:stylesheet>
