Added support for errorURL.
[java-idp.git] / src / schemas / metadata_v12_to_v13.xsl
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!--
3
4         v12_to_v13.xsl
5         
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.
10         
11         Author: Ian A. Young <ian@iay.org.uk>
12
13         $Id$
14 -->
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">
23
24         <!--
25                 Version information for this file.  Remember to peel off the dollar signs
26                 before dropping the text into another versioned file.
27         -->
28         <xsl:param name="cvsId">$Id$</xsl:param>
29
30         <!--
31                 Add a comment to the start of the output file.
32         -->
33         <xsl:template match="/">
34                 <xsl:comment>
35                         <xsl:text>&#10;&#9;***DO NOT EDIT THIS FILE***&#10;&#10;</xsl:text>
36                         <xsl:text>&#9;Converted by:&#10;&#10;&#9;</xsl:text>
37                         <xsl:value-of select="substring-before(substring-after($cvsId, ': '), '$')"/>
38                         <xsl:text>&#10;</xsl:text>
39                 </xsl:comment>
40                 <xsl:apply-templates/>
41         </xsl:template>
42
43         <!--Force UTF-8 encoding for the output.-->
44         <xsl:output omit-xml-declaration="no" method="xml" encoding="UTF-8" indent="yes"/>
45
46         <!--
47                 SiteGroup is the root element for the sites file.  The corresponding element in the new format file
48                 is an EntitiesDescriptor.
49         -->
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>
56                         </xsl:attribute>
57                         <!--
58                                 Pass through text blocks and comments, and any shib elements.
59                                 These may be: OriginSite, DestinationSite or nested SiteGroup.
60                         -->
61                         <xsl:apply-templates select="text()|comment()|shib:*"/>
62                 </EntitiesDescriptor>
63         </xsl:template>
64
65         <!--
66                 Map OriginSite to an EntityDescriptor with a particular format.
67         -->
68         <xsl:template match="shib:OriginSite">
69                 <EntityDescriptor entityID="{@Name}">
70                         <!--
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".
74                         -->
75                         <xsl:apply-templates select="text()|comment()"/>
76                         <!--
77                                 Map HandleService and AttributeAuthority.  We need to pass in the (possibly empty)
78                                 set of Domain elements as a parameter.
79                         -->
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"/>
85                 </EntityDescriptor>
86         </xsl:template>
87         
88         <!--
89                 Map HandleService to IDPSSODescriptor.
90         -->
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">
94                         <!--
95                                 Map @ErrorURL (if present) to @errorURL
96                         -->
97                         <xsl:apply-templates select="../@ErrorURL"/>
98                         <!--
99                                 Extensions appears iff there is something to put in it.
100                         -->
101                         <xsl:if test="boolean($Domain)">
102                                 <Extensions>
103                                         <xsl:apply-templates select="$Domain"/>
104                                 </Extensions>
105                         </xsl:if>
106                         <KeyDescriptor use="signing">
107                                 <ds:KeyInfo>
108                                         <ds:KeyName>
109                                                 <xsl:value-of select="@Name"/>
110                                         </ds:KeyName>
111                                 </ds:KeyInfo>
112                         </KeyDescriptor>
113                         <SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest"
114                                 Location="{@Location}"/>
115                 </IDPSSODescriptor>
116         </xsl:template>
117
118         <!--
119                 Map AttributeAuthority to AttributeAuthorityDescriptor.
120         -->
121         <xsl:template match="shib:AttributeAuthority">
122                 <xsl:param name="Domain"/>
123                 <AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
124                         <!--
125                                 Map @ErrorURL (if present) to @errorURL
126                         -->
127                         <xsl:apply-templates select="../@ErrorURL"/>
128                         <!--
129                                 Extensions appears iff there is something to put in it.
130                         -->
131                         <xsl:if test="boolean($Domain)">
132                                 <Extensions>
133                                         <xsl:apply-templates select="$Domain"/>
134                                 </Extensions>
135                         </xsl:if>
136                         <AttributeService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
137                                 Location="{@Location}"/>
138                 </AttributeAuthorityDescriptor>
139         </xsl:template>
140         
141         <!--
142                 Map Domain to a Scope extension.
143         -->
144         <xsl:template match="shib:Domain">
145                 <shibmeta:Scope>
146                         <xsl:apply-templates select="@regexp"/>
147                         <xsl:value-of select="."/>
148                 </shibmeta:Scope>
149         </xsl:template>
150         
151         <!--
152                 Map DestinationSite to an EntityDescriptor with a particular format.
153         -->
154         <xsl:template match="shib:DestinationSite">
155                 <EntityDescriptor entityID="{@Name}">
156                         <!--
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".
160                         -->
161                         <xsl:apply-templates select="text()|comment()"/>
162                         <!--
163                                 Generate IDPSSODescriptor.
164                         -->
165                         <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
166                                 <!--
167                                         Map @ErrorURL (if present) to @errorURL
168                                 -->
169                                 <xsl:apply-templates select="@ErrorURL"/>
170                                 <!--
171                                         Map AttributeRequester elements to KeyDescriptor elements.
172                                 -->
173                                 <xsl:apply-templates select="shib:AttributeRequester"/>
174                                 <!--
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.
179                                 -->
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>
184                                 </xsl:for-each>
185                         </SPSSODescriptor>
186                         <xsl:call-template name="Alias"/>
187                         <xsl:apply-templates select="shib:Contact"/>
188                 </EntityDescriptor>
189         </xsl:template>
190
191         <!--
192                 Map @ErrorURL to @errorURL
193         -->
194         <xsl:template match="@ErrorURL">
195                 <xsl:attribute name="errorURL"><xsl:value-of select="."/></xsl:attribute>
196         </xsl:template>
197
198         <!--
199                 Map AttributeRequester to KeyDescriptor.
200         -->
201         <xsl:template match="shib:AttributeRequester">
202                 <KeyDescriptor>
203                         <ds:KeyInfo>
204                                 <ds:KeyName>
205                                         <xsl:value-of select="@Name"/>
206                                 </ds:KeyName>
207                         </ds:KeyInfo>
208                 </KeyDescriptor>
209         </xsl:template>
210
211         <!--
212                 Map AssertionConsumerServiceURL to AssertionConsumerService.
213         -->
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}"
218                 />
219         </xsl:template>
220
221         <!--
222                 Named template to map a set of Alias elements to a corresponding Organization.
223         -->
224         <xsl:template name="Alias">
225                 <xsl:if test="boolean(shib:Alias)">
226                         <Organization>
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"/>
230                         </Organization>
231                 </xsl:if>
232         </xsl:template>
233
234         <!--
235                 Map Alias to OrganizationName
236         -->
237         <xsl:template match="shib:Alias" mode="OrganizationName">
238                 <OrganizationName>
239                         <xsl:call-template name="copyXmlLang"/>
240                         <xsl:value-of select="."/>
241                 </OrganizationName>
242         </xsl:template>
243
244         <!--
245                 Map Alias to OrganizationDisplayName
246         -->
247         <xsl:template match="shib:Alias" mode="OrganizationDisplayName">
248                 <OrganizationDisplayName>
249                         <xsl:call-template name="copyXmlLang"/>
250                         <xsl:value-of select="."/>
251                 </OrganizationDisplayName>
252         </xsl:template>
253
254         <!--
255                 Map Alias to OrganizationURL
256         -->
257         <xsl:template match="shib:Alias" mode="OrganizationURL">
258                 <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>
262                 </OrganizationURL>
263         </xsl:template>
264
265         <!--
266                 Copy an xml:lang attribute, or default to "en" if none present.
267         -->
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>
271                 </xsl:if>
272                 <xsl:if test="not(boolean(@xml:lang))">
273                         <xsl:attribute name="xml:lang">en</xsl:attribute>
274                 </xsl:if>
275         </xsl:template>
276
277         <!--
278                 Map Contact to ContactPerson
279         -->
280         <xsl:template match="shib:Contact">
281                 <ContactPerson contactType="{@Type}">
282                         <!--
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.
286                         -->
287                         <GivenName>
288                                 <xsl:value-of select="@Name"/>
289                         </GivenName>
290                         <!--
291                                 E-mail address, but only if it was present in the original.
292                         -->
293                         <xsl:apply-templates select="@Email" mode="Contact"/>
294                 </ContactPerson>
295         </xsl:template>
296
297         <!--
298                 E-mail address for Contact
299         -->
300         <xsl:template match="@Email" mode="Contact">
301                 <EmailAddress>
302                         <xsl:value-of select="."/>
303                 </EmailAddress>
304         </xsl:template>
305
306         <!--
307                 By default, copy referenced attributes through unchanged.
308         -->
309         <xsl:template match="@*">
310                 <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
311         </xsl:template>
312
313         <!--
314                 By default, copy comments through to the output unchanged, but strip extra text.
315         -->
316         <xsl:template match="comment()">
317                 <xsl:copy/>
318         </xsl:template>
319         <xsl:template match="text()"/>
320
321 </xsl:stylesheet>
322