1 <?xml version="1.0" encoding="UTF-8"?>
6 XSL stylesheet converting a Shibboleth 1.2 sites file into the equivalent for
7 Shibboleth 1.3, which is based on the SAML 1.1 profile of the SAML 2.0
8 metadata format. No attempt is made to incorporate the separate trust
9 data used by Shibboleth 1.2.
11 Author: Ian A. Young <ian@iay.org.uk>
15 <xsl:stylesheet version="1.0"
16 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
17 xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
18 xmlns:shib="urn:mace:shibboleth:1.0"
19 xmlns:shibmeta="urn:mace:shibboleth:metadata:1.0"
20 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21 xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
22 exclude-result-prefixes="shib">
25 Version information for this file. Remember to peel off the dollar signs
26 before dropping the text into another versioned file.
28 <xsl:param name="cvsId">$Id$</xsl:param>
31 Add a comment to the start of the output file.
33 <xsl:template match="/">
35 <xsl:text> 	***DO NOT EDIT THIS FILE*** </xsl:text>
36 <xsl:text>	Converted by: 	</xsl:text>
37 <xsl:value-of select="substring-before(substring-after($cvsId, ': '), '$')"/>
38 <xsl:text> </xsl:text>
40 <xsl:apply-templates/>
43 <!--Force UTF-8 encoding for the output.-->
44 <xsl:output omit-xml-declaration="no" method="xml" encoding="UTF-8" indent="yes"/>
47 SiteGroup is the root element for the sites file. The corresponding element in the new format file
48 is an EntitiesDescriptor.
50 <xsl:template match="shib:SiteGroup">
51 <EntitiesDescriptor Name="{@Name}">
52 <xsl:attribute name="xsi:schemaLocation">
53 <xsl:text>urn:oasis:names:tc:SAML:2.0:metadata sstc-saml-schema-metadata-2.0.xsd </xsl:text>
54 <xsl:text>urn:mace:shibboleth:metadata:1.0 shibboleth-metadata-1.0.xsd </xsl:text>
55 <xsl:text>http://www.w3.org/2000/09/xmldsig# xmldsig-core-schema.xsd</xsl:text>
58 Pass through text blocks and comments, and any shib elements.
59 These may be: OriginSite, DestinationSite or nested SiteGroup.
61 <xsl:apply-templates select="text()|comment()|shib:*"/>
66 Map OriginSite to an EntityDescriptor with a particular format.
68 <xsl:template match="shib:OriginSite">
69 <EntityDescriptor entityID="{@Name}">
71 Copy through comments and text blocks at the start of the output element.
72 This means we don't lose comments, but there is no way to guarantee they will
73 come out "in the right place".
75 <xsl:apply-templates select="text()|comment()"/>
77 Map HandleService and AttributeAuthority. We need to pass in the (possibly empty)
78 set of Domain elements as a parameter.
80 <xsl:apply-templates select="shib:HandleService|shib:AttributeAuthority">
81 <xsl:with-param name="Domain" select="shib:Domain"/>
82 </xsl:apply-templates>
83 <xsl:call-template name="Alias"/>
84 <xsl:apply-templates select="shib:Contact"/>
89 Map HandleService to IDPSSODescriptor.
91 <xsl:template match="shib:HandleService">
92 <xsl:param name="Domain"/>
93 <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:mace:shibboleth:1.0">
95 Map @ErrorURL (if present) to @errorURL
97 <xsl:apply-templates select="../@ErrorURL"/>
99 Extensions appears iff there is something to put in it.
101 <xsl:if test="boolean($Domain)">
103 <xsl:apply-templates select="$Domain"/>
106 <KeyDescriptor use="signing">
109 <xsl:value-of select="@Name"/>
113 <SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest"
114 Location="{@Location}"/>
119 Map AttributeAuthority to AttributeAuthorityDescriptor.
121 <xsl:template match="shib:AttributeAuthority">
122 <xsl:param name="Domain"/>
123 <AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
125 Map @ErrorURL (if present) to @errorURL
127 <xsl:apply-templates select="../@ErrorURL"/>
129 Extensions appears iff there is something to put in it.
131 <xsl:if test="boolean($Domain)">
133 <xsl:apply-templates select="$Domain"/>
136 <AttributeService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
137 Location="{@Location}"/>
138 </AttributeAuthorityDescriptor>
142 Map Domain to a Scope extension.
144 <xsl:template match="shib:Domain">
146 <xsl:apply-templates select="@regexp"/>
147 <xsl:value-of select="."/>
152 Map DestinationSite to an EntityDescriptor with a particular format.
154 <xsl:template match="shib:DestinationSite">
155 <EntityDescriptor entityID="{@Name}">
157 Copy through comments and text blocks at the start of the output element.
158 This means we don't lose comments, but there is no way to guarantee they will
159 come out "in the right place".
161 <xsl:apply-templates select="text()|comment()"/>
163 Generate IDPSSODescriptor.
165 <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
167 Map @ErrorURL (if present) to @errorURL
169 <xsl:apply-templates select="@ErrorURL"/>
171 Map AttributeRequester elements to KeyDescriptor elements.
173 <xsl:apply-templates select="shib:AttributeRequester"/>
175 Map the AssertionConsumerServiceURL elements to
176 AssertionConsumerService elements. The latter require unique
177 integer indices, so do this by looping over them and using
178 position in the loop to generate each index.
180 <xsl:for-each select="shib:AssertionConsumerServiceURL">
181 <xsl:apply-templates select=".">
182 <xsl:with-param name="index" select="position()-1"/>
183 </xsl:apply-templates>
186 <xsl:call-template name="Alias"/>
187 <xsl:apply-templates select="shib:Contact"/>
192 Map @ErrorURL to @errorURL
194 <xsl:template match="@ErrorURL">
195 <xsl:attribute name="errorURL"><xsl:value-of select="."/></xsl:attribute>
199 Map AttributeRequester to KeyDescriptor.
201 <xsl:template match="shib:AttributeRequester">
205 <xsl:value-of select="@Name"/>
212 Map AssertionConsumerServiceURL to AssertionConsumerService.
214 <xsl:template match="shib:AssertionConsumerServiceURL">
215 <xsl:param name="index"/>
216 <AssertionConsumerService index="{$index}"
217 Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="{@Location}"
222 Named template to map a set of Alias elements to a corresponding Organization.
224 <xsl:template name="Alias">
225 <xsl:if test="boolean(shib:Alias)">
227 <xsl:apply-templates select="shib:Alias" mode="OrganizationName"/>
228 <xsl:apply-templates select="shib:Alias" mode="OrganizationDisplayName"/>
229 <xsl:apply-templates select="shib:Alias" mode="OrganizationURL"/>
235 Map Alias to OrganizationName
237 <xsl:template match="shib:Alias" mode="OrganizationName">
239 <xsl:call-template name="copyXmlLang"/>
240 <xsl:value-of select="."/>
245 Map Alias to OrganizationDisplayName
247 <xsl:template match="shib:Alias" mode="OrganizationDisplayName">
248 <OrganizationDisplayName>
249 <xsl:call-template name="copyXmlLang"/>
250 <xsl:value-of select="."/>
251 </OrganizationDisplayName>
255 Map Alias to OrganizationURL
257 <xsl:template match="shib:Alias" mode="OrganizationURL">
259 <xsl:call-template name="copyXmlLang"/>
260 <!-- there is nothing to map, but the URL is mandatory -->
261 <xsl:text>http://www.example.com/</xsl:text>
266 Copy an xml:lang attribute, or default to "en" if none present.
268 <xsl:template name="copyXmlLang">
269 <xsl:if test="boolean(@xml:lang)">
270 <xsl:attribute name="xml:lang"><xsl:value-of select="@xml:lang"/></xsl:attribute>
272 <xsl:if test="not(boolean(@xml:lang))">
273 <xsl:attribute name="xml:lang">en</xsl:attribute>
278 Map Contact to ContactPerson
280 <xsl:template match="shib:Contact">
281 <ContactPerson contactType="{@Type}">
283 There is no real mapping for the Name attribute, so we rather arbitrarily
284 dump that into GivenName rather than trying to split it into a GivenName and
285 a SurName or something complicated like that.
288 <xsl:value-of select="@Name"/>
291 E-mail address, but only if it was present in the original.
293 <xsl:apply-templates select="@Email" mode="Contact"/>
298 E-mail address for Contact
300 <xsl:template match="@Email" mode="Contact">
302 <xsl:value-of select="."/>
307 By default, copy referenced attributes through unchanged.
309 <xsl:template match="@*">
310 <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
314 By default, copy comments through to the output unchanged, but strip extra text.
316 <xsl:template match="comment()">
319 <xsl:template match="text()"/>