source: subversion/utils/osmarender/osmarender.xsl @ 1023

Last change on this file since 1023 was 1023, checked in by steve, 14 years ago

osmarender added

File size: 23.7 KB
Line 
1<?xml version='1.0' standalone='no'?>
2<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp '&#160;'> ]>
3
4<!-- Osmarender.xsl 1.6 -->
5
6<!-- Revision history:
7     1.0 2006-03-21 Initial version
8     1.1 2006-03-23 Remove <html> and <body> tags
9     1.2 2006-03-24 Support for ways
10     1.3 2006-04-10 width key will override line width
11                    Implements nested rules
12                    General restructuring
13                    Implements <symbol> instruction
14     1.4 2006-04-11 Implements <textPath> instruction for text on Segments and Ways
15     1.5 2006-04-11 Fix bug that generated invalid xsl-stylesheet PI
16                    Fix bug resulting in superflous white space output
17                    Fix bug causing dy attribute on <textPath> element rather than <text> element
18     1.6 2006-04-12 Fix bug with <text> instructions choking on <segment> and <way> elements in Batik
19-->
20
21<!-- Osmarender rules files contain two kinds of element; rules and instructions.  Rule elements provide a
22     simple selection mechanism.  Instructions define what to do with the elements that match the rules.
23     
24     Rules are simple filters based on keys and values (the k and v attributes).  For example:
25      <rule k="highway" v="motorway">...</rule>
26     will select all elements (segments, ways and nodes) that have a key of highway with a value of motorway.
27     Rules can be nested to provide a logical "and".  For example:
28       <rule k="highway" v="primary">
29         <rule k="abutters" v="retail">
30          ...
31         </rule>
32       </rule>
33     would select all segments that are primary roads *and* abutted by retail premises.
34     
35     Instructions define what to do with the elements that match the rules.  Typically, they render the element
36     in some way by generating an svg command to draw a line or circle etc.  In most cases the attributes of
37     the instruction are copied to the corresponding svg command.  For example:
38       <line stroke-width="10"/>
39     will generate a corresponding svg command to draw a line with a width of 10px.
40-->
41
42<xsl:stylesheet 
43 version="1.0"
44 xmlns="http://www.w3.org/2000/svg"
45 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
46 xmlns:xlink="http://www.w3.org/1999/xlink">
47
48  <xsl:variable name='scale' select='/rules/@scale'/>
49  <xsl:variable name='data' select='document(/rules/@data)'/>
50  <xsl:key name='nodeById' match='/osm/node' use='@id'/>
51  <xsl:key name='segmentById' match='/osm/segment' use='@id'/>
52
53  <!-- Automatically calculate the size of the bounding box -->
54  <xsl:variable name="trlat">
55    <xsl:for-each select="$data/osm/node/@lat">
56      <xsl:sort data-type="number" order="descending"/>
57      <xsl:if test="position()=1">
58        <xsl:value-of select="."/>
59      </xsl:if>
60    </xsl:for-each>
61  </xsl:variable>
62  <xsl:variable name="bllat">
63    <xsl:for-each select="$data/osm/node/@lat">
64      <xsl:sort data-type="number" order="ascending"/>
65      <xsl:if test="position()=1">
66        <xsl:value-of select="."/>
67      </xsl:if>
68    </xsl:for-each>
69  </xsl:variable>
70  <xsl:variable name="trlon">
71    <xsl:for-each select="$data/osm/node/@lon">
72      <xsl:sort data-type="number" order="descending"/>
73      <xsl:if test="position()=1">
74        <xsl:value-of select="."/>
75      </xsl:if>
76    </xsl:for-each>
77  </xsl:variable>
78  <xsl:variable name="bllon">
79    <xsl:for-each select="$data/osm/node/@lon">
80      <xsl:sort data-type="number" order="ascending"/>
81      <xsl:if test="position()=1">
82        <xsl:value-of select="."/>
83      </xsl:if>
84    </xsl:for-each>
85  </xsl:variable>
86 
87  <xsl:variable name='width' select='(number($trlon)-number($bllon))*10000*$scale' />
88  <xsl:variable name='height' select='(number($trlat)-number($bllat))*10000*$scale*1.6' />
89
90  <!-- Main template -->
91  <xsl:template match="/rules">     
92
93    <!-- Include an external css stylesheet if one was specified in the rules file -->
94    <xsl:if test='@xml-stylesheet'>
95      <xsl:processing-instruction name='xml-stylesheet'>
96        href="<xsl:value-of select='@xml-stylesheet'/>" type="text/css"
97      </xsl:processing-instruction>
98    </xsl:if>
99
100    <svg
101     version="1.1"
102     baseProfile="full"
103     height="{$height}px"
104     width="{$width}px">   
105
106      <defs>
107       
108        <!-- Get any <defs> from the rules file -->
109        <xsl:copy-of select='defs/*'/>
110       
111        <!-- Get CSS definitions from the rules file (deprecated) -->
112        <style type='text/css'>
113          <xsl:value-of select='style'/>
114        </style>
115      </defs>
116
117      <!-- Process all the rules -->
118      <xsl:variable name='allElements' select='$data/osm/*' />
119       <xsl:apply-templates select='/rules/rule'>
120         <xsl:with-param name='elements' select='$allElements' />
121       </xsl:apply-templates>
122
123      <!-- Draw the scale in the bottom left corner -->
124      <xsl:call-template name="scaleDraw"/>
125
126      <!-- Attribute to OSM -->
127      <xsl:call-template name="attribution"/>
128
129      <!-- Creative commons license -->
130      <xsl:call-template name="license"/>
131    </svg>
132
133  </xsl:template>
134
135
136  <!-- ============================================================================= -->
137  <!-- Rule processing template                                                      -->
138  <!-- ============================================================================= -->
139
140  <!-- For each rule apply line, circle, text, etc templates.  Then apply the rule template recursively for each nested rule --> 
141  <xsl:template match='rule'>
142    <xsl:param name='elements' />
143
144    <!-- This is the rule currently being processed -->
145    <xsl:variable name='rule' select='.'/>
146
147    <xsl:choose>
148      <xsl:when test='$rule/@v="~"'>
149        <xsl:variable name='elementsWithoutKey' select='$elements[count(tag[@k=$rule/@k])=0]'/>
150        <xsl:apply-templates select='*'>
151          <xsl:with-param name='elements' select='$elementsWithoutKey' />
152          <xsl:with-param name='rule' select='$rule'/>
153        </xsl:apply-templates>
154      </xsl:when>
155      <xsl:otherwise>
156        <xsl:variable name='elementsWithKey' select='$elements[tag[@k=$rule/@k and @v=$rule/@v]]'/>
157        <xsl:apply-templates select='*'>
158          <xsl:with-param name='elements' select='$elementsWithKey' />
159          <xsl:with-param name='rule' select='$rule'/>
160        </xsl:apply-templates>
161      </xsl:otherwise>
162    </xsl:choose>
163  </xsl:template>
164
165
166  <!-- ============================================================================= -->
167  <!-- Templates to process line, circle, text, etc instructions                     -->
168  <!-- ============================================================================= -->
169  <!-- Each template is passed a variable containing the set of elements that need to
170       be processed.  The set of elements is already determined by the rules, so
171       these templates don't need to know anything about the rules context they are in. -->
172
173  <!-- Process a <line> instruction -->
174  <xsl:template match='line'>
175    <xsl:param name='elements' />
176
177    <!-- This is the instruction that is currently being processed -->
178    <xsl:variable name='instruction' select='.'/>
179
180    <g>
181      <xsl:copy-of select='@*'/> <!-- Add all the attributes of the <line> instruction to the <g> element -->
182
183      <!-- For each segment and way -->
184      <xsl:apply-templates select='$elements' mode='line'>
185        <xsl:with-param name='instruction' select='$instruction' />
186      </xsl:apply-templates>
187
188    </g>
189  </xsl:template>
190
191
192  <!-- Suppress output of any unhandled elements -->
193  <xsl:template match='*' mode='line'/>
194 
195 
196  <!-- Draw lines for a segment -->
197  <xsl:template match='segment' mode='line'>
198    <xsl:param name='instruction' />
199
200    <xsl:call-template name='drawLine'>
201      <xsl:with-param name='instruction' select='$instruction'/>
202      <xsl:with-param name='segment' select='.'/>
203    </xsl:call-template>
204
205  </xsl:template>
206
207
208  <!-- Draw lines for a way (draw all the segments that belong to the way) -->
209  <xsl:template match='way' mode='line'>
210    <xsl:param name='instruction' />
211
212    <!-- The current <way> element -->
213    <xsl:variable name='way' select='.' />
214   
215    <xsl:for-each select='seg'>
216      <xsl:variable name='segmentId' select='@id'/>
217      <xsl:for-each select='key("segmentById",$segmentId)'>
218        <xsl:call-template name='drawLine'>
219          <xsl:with-param name='instruction' select='$instruction'/>
220          <xsl:with-param name='segment' select='.'/>
221          <xsl:with-param name='way' select='$way'/>
222        </xsl:call-template>
223      </xsl:for-each>
224    </xsl:for-each>
225
226  </xsl:template>
227 
228
229  <!-- Process circle instruction -->
230  <xsl:template match='circle'>
231    <xsl:param name='elements'/>
232
233    <!-- This is the instruction that is currently being processed -->
234    <xsl:variable name='instruction' select='.' />
235
236    <xsl:for-each select='$elements[name()="node"]'>
237      <xsl:call-template name='drawCircle'>
238        <xsl:with-param name='instruction' select='$instruction'/>
239      </xsl:call-template>         
240    </xsl:for-each>
241  </xsl:template>
242
243
244  <!-- Process a symbol instruction -->
245  <xsl:template match='symbol'>
246    <xsl:param name='elements'/>
247
248    <!-- This is the instruction that is currently being processed -->
249    <xsl:variable name='instruction' select='.' />
250
251    <xsl:for-each select='$elements[name()="node"]'>
252      <xsl:call-template name='drawSymbol'>
253        <xsl:with-param name='instruction' select='$instruction'/>
254      </xsl:call-template>
255    </xsl:for-each>
256  </xsl:template>
257
258
259  <!-- Process a <text> instruction -->
260  <xsl:template match='text'>
261    <xsl:param name='elements'/>
262
263    <!-- This is the instruction that is currently being processed -->
264    <xsl:variable name='instruction' select='.' />
265   
266    <!-- Select all <node> elements that have a key that matches the k attribute of the text instruction -->
267    <xsl:for-each select='$elements[name()="node"][tag[@k=$instruction/@k]]'>
268        <xsl:call-template name='renderText'>
269          <xsl:with-param name='instruction' select='$instruction'/>
270        </xsl:call-template>         
271    </xsl:for-each>
272  </xsl:template>
273
274
275  <!-- Process a <textPath> instruction -->
276  <xsl:template match='textPath'>
277    <xsl:param name='elements'/>
278
279    <!-- This is the instruction that is currently being processed -->
280    <xsl:variable name='instruction' select='.' />
281   
282    <!-- Select all elements that have a key that matches the k attribute of the textPath instruction -->
283    <xsl:apply-templates select='$elements[tag[@k=$instruction/@k]]' mode='textPath'>
284      <xsl:with-param name='instruction' select='$instruction' />
285    </xsl:apply-templates>
286  </xsl:template>
287
288
289  <!-- Suppress output of any unhandled elements -->
290  <xsl:template match='*' mode='textPath'/>
291
292
293  <!-- Render textPaths for a segment -->
294  <xsl:template match='segment' mode='textPath'>
295    <xsl:param name='instruction' />
296
297    <!-- Generate the path for the segment -->
298    <xsl:variable name='pathData'>
299      <xsl:call-template name='segmentPath'/>
300    </xsl:variable>
301
302    <defs>
303      <path id="segment_{@id}" d="{$pathData}"/>
304    </defs>
305
306    <xsl:call-template name='renderTextPath'>
307      <xsl:with-param name='instruction' select='$instruction'/>
308      <xsl:with-param name='pathId' select='concat("segment_",@id)'/>
309    </xsl:call-template>
310
311  </xsl:template>
312
313
314  <!-- Render textPaths for a way -->
315  <xsl:template match='way' mode='textPath'>
316    <xsl:param name='instruction' />
317
318    <!-- The current <way> element -->
319    <xsl:variable name='way' select='.' />
320   
321    <!-- Generate the path for the way -->
322    <xsl:variable name='pathData'>
323      <xsl:for-each select='seg'>
324        <xsl:variable name='segmentId' select='@id'/>
325        <xsl:for-each select='key("segmentById",$segmentId)'>
326            <xsl:call-template name='segmentPath'/>
327        </xsl:for-each>
328      </xsl:for-each>
329    </xsl:variable>
330
331    <defs>
332      <path id="way_{@id}" d="{$pathData}"/>
333    </defs>
334
335    <xsl:call-template name='renderTextPath'>
336      <xsl:with-param name='instruction' select='$instruction'/>
337      <xsl:with-param name='pathId' select='concat("way_",@id)'/>
338    </xsl:call-template>
339
340  </xsl:template>
341
342
343  <!-- Return the path for a segment -->
344  <xsl:template name='segmentPath'>
345    <xsl:variable name='from' select='@from'/>
346    <xsl:variable name='to' select='@to'/>
347    <xsl:variable name='fromNode' select='key("nodeById",$from)'/>
348    <xsl:variable name='toNode' select='key("nodeById",$to)'/>
349
350    <xsl:variable name='x1' select='round(($width)-((($trlon)-($fromNode/@lon))*10000*$scale))' />
351    <xsl:variable name='y1' select='round(($height)+((($bllat)-($fromNode/@lat))*10000*$scale*1.6))'/>
352    <xsl:variable name='x2' select='round(($width)-((($trlon)-($toNode/@lon))*10000*$scale))'/>
353    <xsl:variable name='y2' select='round(($height)+((($bllat)-($toNode/@lat))*10000*$scale*1.6))'/>
354    <!-- Only really need the M for the first segment if the segments are contiguous -->
355    <xsl:text>M</xsl:text>
356    <xsl:value-of select='$x1'/>
357    <xsl:text> </xsl:text>
358    <xsl:value-of select='$y1'/>
359    <xsl:text>L</xsl:text>
360    <xsl:value-of select='$x2'/>
361    <xsl:text> </xsl:text>
362    <xsl:value-of select='$y2'/>
363  </xsl:template>
364   
365 
366 
367  <!-- ============================================================================= -->
368  <!-- Drawing templates                                                             -->
369  <!-- ============================================================================= -->
370
371  <!-- Draw a line for the current <segment> element using the formatting of the current <line> instruction -->
372  <xsl:template name='drawLine'>
373    <xsl:param name='instruction'/>
374    <xsl:param name='segment'/> <!-- The current segment element -->
375    <xsl:param name='way'/>  <!-- The current way element if applicable -->
376
377    <xsl:variable name='from' select='@from'/>
378    <xsl:variable name='to' select='@to'/>
379    <xsl:variable name='fromNode' select='key("nodeById",$from)'/>
380    <xsl:variable name='toNode' select='key("nodeById",$to)'/>
381
382    <xsl:variable name='x1' select='round(($width)-((($trlon)-($fromNode/@lon))*10000*$scale))' />
383    <xsl:variable name='y1' select='round(($height)+((($bllat)-($fromNode/@lat))*10000*$scale*1.6))'/>
384    <xsl:variable name='x2' select='round(($width)-((($trlon)-($toNode/@lon))*10000*$scale))'/>
385    <xsl:variable name='y2' select='round(($height)+((($bllat)-($toNode/@lat))*10000*$scale*1.6))'/>
386   
387    <line>
388      <xsl:attribute name='x1'><xsl:value-of select='$x1'/></xsl:attribute>
389      <xsl:attribute name='y1'><xsl:value-of select='$y1'/></xsl:attribute>
390      <xsl:attribute name='x2'><xsl:value-of select='$x2'/></xsl:attribute>
391      <xsl:attribute name='y2'><xsl:value-of select='$y2'/></xsl:attribute>
392      <!-- If the current <segment> or <way> element has a width key then use it's value to override the stroke-width of the line -->
393      <xsl:if test='$segment/tag[@k="width"]'>
394        <xsl:attribute name='stroke-width'><xsl:value-of select='$segment/tag[@k="width"]/@v'/></xsl:attribute> 
395      </xsl:if>
396      <xsl:if test='$way'>
397        <xsl:if test='$way/tag[@k="width"]'>
398          <xsl:attribute name='stroke-width'><xsl:value-of select='$way/tag[@k="width"]/@v'/></xsl:attribute> 
399        </xsl:if>
400      </xsl:if>
401    </line>
402
403  </xsl:template>
404
405
406  <!-- Draw a circle for the current <node> element using the formatting of the current <circle> instruction -->
407  <xsl:template name='drawCircle'>
408    <xsl:param name='instruction'/>
409
410    <xsl:variable name='x' select='($width)-((($trlon)-(@lon))*10000*$scale)' />
411    <xsl:variable name='y' select='($height)+((($bllat)-(@lat))*10000*$scale*1.6)'/>
412    <xsl:variable name='x1'>
413      <xsl:choose>
414        <xsl:when test='$instruction/@x-offset'>
415          <xsl:value-of select='number($x)+number($instruction/@x-offset)'/>
416        </xsl:when>
417        <xsl:otherwise>
418          <xsl:value-of select='number($x)'/>
419        </xsl:otherwise>
420      </xsl:choose>
421    </xsl:variable>
422    <xsl:variable name='y1'>
423      <xsl:choose>
424        <xsl:when test='$instruction/@y-offset'>
425          <xsl:value-of select='number($y)+number($instruction/@y-offset)'/>
426        </xsl:when>
427        <xsl:otherwise>
428          <xsl:value-of select='number($y)'/>
429        </xsl:otherwise>
430      </xsl:choose>
431    </xsl:variable>
432
433    <circle r='1' cx='{$x1}' cy='{$y1}'>
434        <xsl:copy-of select='$instruction/@*'/> <!-- Copy all the attributes from the <circle> instruction -->   
435    </circle>
436   
437  </xsl:template>
438
439
440  <!-- Draw a symbol for the current <node> element using the formatting of the current <symbol> instruction -->
441  <xsl:template name='drawSymbol'>
442    <xsl:param name='instruction'/>
443
444    <xsl:variable name='x' select='($width)-((($trlon)-(@lon))*10000*$scale)' />
445    <xsl:variable name='y' select='($height)+((($bllat)-(@lat))*10000*$scale*1.6)'/>
446    <xsl:variable name='x1'>
447      <xsl:choose>
448        <xsl:when test='$instruction/@x-offset'>
449          <xsl:value-of select='number($x)+number($instruction/@x-offset)'/>
450        </xsl:when>
451        <xsl:otherwise>
452          <xsl:value-of select='number($x)'/>
453        </xsl:otherwise>
454      </xsl:choose>
455    </xsl:variable>
456    <xsl:variable name='y1'>
457      <xsl:choose>
458        <xsl:when test='$instruction/@y-offset'>
459          <xsl:value-of select='number($y)+number($instruction/@y-offset)'/>
460        </xsl:when>
461        <xsl:otherwise>
462          <xsl:value-of select='number($y)'/>
463        </xsl:otherwise>
464      </xsl:choose>
465    </xsl:variable>
466
467    <use x='{$x1}' y='{$y1}'>
468        <xsl:copy-of select='$instruction/@*'/> <!-- Copy all the attributes from the <circle> instruction -->   
469    </use>
470   
471  </xsl:template>
472
473
474  <!-- Render the appropriate attribute of the current <node> element using the formatting of the current <text> instruction -->
475  <xsl:template name='renderText'>
476    <xsl:param name='instruction'/>
477   
478    <xsl:variable name='x' select='($width)-((($trlon)-(@lon))*10000*$scale)' />
479    <xsl:variable name='y' select='($height)+((($bllat)-(@lat))*10000*$scale*1.6)'/>
480    <xsl:variable name='x1'>
481      <xsl:choose>
482        <xsl:when test='$instruction/@x-offset'>
483          <xsl:value-of select='number($x)+number($instruction/@x-offset)'/>
484        </xsl:when>
485        <xsl:otherwise>
486          <xsl:value-of select='number($x)'/>
487        </xsl:otherwise>
488      </xsl:choose>
489    </xsl:variable>
490    <xsl:variable name='y1'>
491      <xsl:choose>
492        <xsl:when test='$instruction/@y-offset'>
493          <xsl:value-of select='number($y)+number($instruction/@y-offset)'/>
494        </xsl:when>
495        <xsl:otherwise>
496          <xsl:value-of select='number($y)'/>
497        </xsl:otherwise>
498      </xsl:choose>
499    </xsl:variable>
500    <text>
501      <xsl:copy-of select='$instruction/@*'/>   
502      <xsl:attribute name='x'><xsl:value-of select='$x1'/></xsl:attribute>
503      <xsl:attribute name='y'><xsl:value-of select='$y1'/></xsl:attribute>
504      <xsl:value-of select='tag[@k=$instruction/@k]/@v'/>
505    </text>
506  </xsl:template>
507
508
509  <!-- Render the appropriate attribute of the current <segment> element using the formatting of the current <textPath> instruction -->
510  <xsl:template name='renderTextPath'>
511    <xsl:param name='instruction'/>
512    <xsl:param name='pathId'/>
513   
514    <text>
515      <xsl:apply-templates select='$instruction/@*' mode='renderTextPath-text'/>
516      <textPath xlink:href="#{$pathId}">
517        <xsl:apply-templates select='$instruction/@*' mode='renderTextPath-textPath'/>
518        <xsl:value-of select='tag[@k=$instruction/@k]/@v'/>
519      </textPath>
520    </text>
521  </xsl:template>
522
523
524  <!-- Suppress the following attributes, allow everything else -->
525  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength" mode='renderTextPath-text'>
526  </xsl:template>
527
528  <xsl:template match="@*" mode='renderTextPath-text'>
529    <xsl:copy/>
530  </xsl:template>
531
532  <!-- Allow the following attributes, suppress everything else -->
533  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength" mode='renderTextPath-textPath'>
534    <xsl:copy/>
535  </xsl:template>
536
537  <xsl:template match="@*" mode='renderTextPath-textPath'>
538  </xsl:template>
539
540
541  <!-- ============================================================================= -->
542  <!-- Fairly static stuff                                                           -->
543  <!-- ============================================================================= -->
544
545  <!-- Draw an approximate scale in the bottom left corner of the map -->
546  <xsl:template name='scaleDraw'>
547    <xsl:variable name='x1' select='round(($width)-((($trlon)-(number($bllon)))*10000*$scale))+20' />
548    <xsl:variable name='y1' select='round(($height)+((($bllat)-(number($bllat)))*10000*$scale*1.6))-20'/>
549    <xsl:variable name='x2' select='round(($width)-((($trlon)-(number($bllon)+0.0089928))*10000*$scale))+20'/>
550    <xsl:variable name='y2' select='round(($height)+((($bllat)-(number($bllat)))*10000*$scale*1.6))-20'/>
551   
552    <text font-family='Verdana' font-size='10px' fill='black'>
553      <xsl:attribute name='x'><xsl:value-of select='$x1'/></xsl:attribute>
554      <xsl:attribute name='y'><xsl:value-of select='number($y1)-10'/></xsl:attribute>
555      0
556    </text>
557
558    <text font-family='Verdana' font-size='10px' fill='black'>
559      <xsl:attribute name='x'><xsl:value-of select='$x2'/></xsl:attribute>
560      <xsl:attribute name='y'><xsl:value-of select='number($y2)-10'/></xsl:attribute>
561      1km
562    </text>
563
564    <line style="stroke-width: 4; stroke-linecap: butt; stroke: #000000;">
565      <xsl:attribute name='x1'><xsl:value-of select='$x1'/></xsl:attribute>
566      <xsl:attribute name='y1'><xsl:value-of select='$y1'/></xsl:attribute>
567      <xsl:attribute name='x2'><xsl:value-of select='$x2'/></xsl:attribute>
568      <xsl:attribute name='y2'><xsl:value-of select='$y2'/></xsl:attribute>
569    </line>
570
571    <line style="stroke-width: 1; stroke-linecap: butt; stroke: #000000;">
572      <xsl:attribute name='x1'><xsl:value-of select='number($x1)'/></xsl:attribute>
573      <xsl:attribute name='y1'><xsl:value-of select='number($y1)'/></xsl:attribute>
574      <xsl:attribute name='x2'><xsl:value-of select='number($x1)'/></xsl:attribute>
575      <xsl:attribute name='y2'><xsl:value-of select='number($y1)-10'/></xsl:attribute>
576    </line>
577
578    <line style="stroke-width: 1; stroke-linecap: butt; stroke: #000000;">
579      <xsl:attribute name='x1'><xsl:value-of select='number($x2)'/></xsl:attribute>
580      <xsl:attribute name='y1'><xsl:value-of select='number($y2)'/></xsl:attribute>
581      <xsl:attribute name='x2'><xsl:value-of select='number($x2)'/></xsl:attribute>
582      <xsl:attribute name='y2'><xsl:value-of select='number($y2)-10'/></xsl:attribute>
583    </line>
584
585  </xsl:template>
586
587
588  <!-- Draw the copyright and attribution details at the bottom of the map -->
589  <xsl:template name='attribution'>
590    <a xlink:href='http:www.openstreetmap.org'>
591      <image x="{number($width)-360}" y="{number($height)-70}" width="150px" height="50px"
592              xlink:href="http://wiki.openstreetmap.org/images/8/86/Osm_linkage.png">
593        <title>Copyright OpenStreetMap 2006</title>
594      </image>
595      <text font-family='Verdana' font-size='8px' fill='black' x='{number($width)-360}' y='{number($height)-10}'>
596      Copyright 2006, OpenStreetMap.org
597      </text>
598    </a>       
599  </xsl:template>
600 
601
602  <!-- Draw the license details at the bottom right of the map -->
603  <xsl:template name='license'>
604    <!--Creative Commons License-->
605    <a xlink:href='http://creativecommons.org/licenses/by-sa/2.0/'>
606      <image x="{number($width)-190}" y="{number($height)-60}" width="88px" height="31px"
607              xlink:href="http://www.openstreetmap.org/images/somerights20.png">
608        <title>Creative Commons - Some Rights Reserved - Attribution-ShareAlike 2.0</title>
609      </image>
610      <text font-family='Verdana' font-size='8px' fill='black' x='{number($width)-190}' y='{number($height)-20}'>
611      This work is licensed under a Creative
612      </text>
613      <text font-family='Verdana' font-size='8px' fill='black' x='{number($width)-190}' y='{number($height)-10}'>
614      Commons Attribution-ShareAlike 2.0 License.
615      </text>
616    </a>       
617  </xsl:template>
618 
619</xsl:stylesheet>
Note: See TracBrowser for help on using the repository browser.