source: subversion/applications/rendering/osmarender6/osmarender.xsl @ 6083

Last change on this file since 6083 was 6083, checked in by bobkare, 12 years ago

Support for symbols on areas

File size: 129.3 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<!--
3==============================================================================
4
5Osmarender 6.0 Alpha 6
6    with - orig area generation
7         - one node way filtered out
8         - filtered out missing multipolygon relation members from areas
9         - filtered out missing node ref from ways
10
11==============================================================================
12
13Copyright (C) 2006-2007  Etienne Cherdlu, Jochen Topf
14
15This program is free software; you can redistribute it and/or modify
16it under the terms of the GNU General Public License as published by
17the Free Software Foundation; either version 2 of the License, or
18(at your option) any later version.
19
20This program is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23GNU General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with this program; if not, write to the Free Software
27Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
28
29==============================================================================
30-->
31<xsl:stylesheet
32  xmlns="http://www.w3.org/2000/svg"
33  xmlns:svg="http://www.w3.org/2000/svg"
34  xmlns:xlink="http://www.w3.org/1999/xlink"
35  xmlns:xi="http://www.w3.org/2001/XInclude"
36  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
37  xmlns:cc="http://web.resource.org/cc/"
38  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
39  xmlns:dc="http://purl.org/dc/elements/1.1/"
40  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
41  version="1.0">
42
43  <xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="UTF-8"/>
44
45  <xsl:param name="osmfile" select="/rules/@data"/>
46  <xsl:param name="title" select="/rules/@title"/>
47
48  <xsl:param name="scale" select="/rules/@scale"/>
49  <xsl:param name="symbolScale" select="/rules/@symbolScale"/>
50  <xsl:param name='textAttenuation' select='/rules/@textAttenuation'/>
51  <xsl:param name="withOSMLayers" select="/rules/@withOSMLayers"/>
52  <xsl:param name="svgBaseProfile" select="/rules/@svgBaseProfile"/>
53  <xsl:param name="symbolsDir" select="/rules/@symbolsDir"/>
54
55  <xsl:param name="showGrid" select="/rules/@showGrid"/>
56  <xsl:param name="showBorder" select="/rules/@showBorder"/>
57  <xsl:param name="showScale" select="/rules/@showScale"/>
58  <xsl:param name="showLicense" select="/rules/@showLicense"/>
59
60  <xsl:key name="nodeById" match="/osm/node" use="@id"/>
61  <xsl:key name="wayById" match="/osm/way" use="@id"/>
62  <xsl:key name="wayByNode" match="/osm/way" use="nd/@ref"/>
63  <xsl:key name="relationByWay" match="/osm/relation" use="member/@ref"/>
64
65  <xsl:variable name="data" select="document($osmfile)"/>
66
67  <!-- Use a web-service (if available) to get the current date -->
68  <xsl:variable name="now" select="document('http://xobjex.com/service/date.xsl')" />
69  <xsl:variable name="date">
70    <xsl:choose>
71      <xsl:when test="$now">
72        <xsl:value-of select="substring($now/date/utc/@stamp,1,10)" />
73        <!-- Assumes 4 digit year -->
74      </xsl:when>
75      <xsl:otherwise>2007-01-01</xsl:otherwise>
76    </xsl:choose>
77  </xsl:variable>
78  <xsl:variable name="year">
79    <xsl:choose>
80      <xsl:when test="$now">
81        <xsl:value-of select="$now/date/utc/year" />
82      </xsl:when>
83      <xsl:otherwise>2007</xsl:otherwise>
84    </xsl:choose>
85  </xsl:variable>
86
87  <!-- extra height for marginalia at top -->
88  <xsl:variable name="marginaliaTopHeight">
89    <xsl:choose>
90      <xsl:when test="$title != ''">40</xsl:when>
91      <xsl:when test="($title = '') and ($showBorder = 'yes')">1.5</xsl:when>
92      <xsl:otherwise>0</xsl:otherwise>
93    </xsl:choose>
94  </xsl:variable>
95
96  <!-- extra height for marginalia at bottom -->
97  <xsl:variable name="marginaliaBottomHeight">
98    <xsl:choose>
99      <xsl:when test="($showScale = 'yes') or ($showLicense = 'yes')">45</xsl:when>
100      <xsl:when test="($showScale != 'yes') and ($showLicense != 'yes') and ($showBorder = 'yes')">1.5</xsl:when>
101      <xsl:otherwise>0</xsl:otherwise>
102    </xsl:choose>
103  </xsl:variable>
104
105  <!-- extra width for border -->
106  <xsl:variable name="extraWidth">
107    <xsl:choose>
108      <xsl:when test="$showBorder = 'yes'">3</xsl:when>
109      <xsl:otherwise>0</xsl:otherwise>
110    </xsl:choose>
111  </xsl:variable>
112
113  <!-- extra height for border -->
114  <xsl:variable name="extraHeight">
115    <xsl:choose>
116      <xsl:when test="($title = '') and ($showBorder = 'yes')">3</xsl:when>
117      <xsl:otherwise>0</xsl:otherwise>
118    </xsl:choose>
119  </xsl:variable>
120
121  <!-- Calculate the size of the bounding box based on the file content -->
122  <xsl:variable name="bllat">
123    <xsl:for-each select="$data/osm/node/@lat">
124      <xsl:sort data-type="number" order="ascending"/>
125      <xsl:if test="position()=1">
126        <xsl:value-of select="."/>
127      </xsl:if>
128    </xsl:for-each>
129  </xsl:variable>
130  <xsl:variable name="bllon">
131    <xsl:for-each select="$data/osm/node/@lon">
132      <xsl:sort data-type="number" order="ascending"/>
133      <xsl:if test="position()=1">
134        <xsl:value-of select="."/>
135      </xsl:if>
136    </xsl:for-each>
137  </xsl:variable>
138  <xsl:variable name="trlat">
139    <xsl:for-each select="$data/osm/node/@lat">
140      <xsl:sort data-type="number" order="descending"/>
141      <xsl:if test="position()=1">
142        <xsl:value-of select="."/>
143      </xsl:if>
144    </xsl:for-each>
145  </xsl:variable>
146  <xsl:variable name="trlon">
147    <xsl:for-each select="$data/osm/node/@lon">
148      <xsl:sort data-type="number" order="descending"/>
149      <xsl:if test="position()=1">
150        <xsl:value-of select="."/>
151      </xsl:if>
152    </xsl:for-each>
153  </xsl:variable>
154  <xsl:variable name="bottomLeftLatitude">
155    <xsl:choose>
156      <xsl:when test="/rules/bounds">
157        <xsl:value-of select="/rules/bounds/@minlat"/>
158      </xsl:when>
159      <xsl:when test="$data/osm/bounds">
160        <xsl:value-of select="$data/osm/bounds/@request_minlat"/>
161      </xsl:when>
162      <xsl:otherwise>
163        <xsl:value-of select="$bllat"/>
164      </xsl:otherwise>
165    </xsl:choose>
166  </xsl:variable>
167  <xsl:variable name="bottomLeftLongitude">
168    <xsl:choose>
169      <xsl:when test="/rules/bounds">
170        <xsl:value-of select="/rules/bounds/@minlon"/>
171      </xsl:when>
172      <xsl:when test="$data/osm/bounds">
173        <xsl:value-of select="$data/osm/bounds/@request_minlon"/>
174      </xsl:when>
175      <xsl:otherwise>
176        <xsl:value-of select="$bllon"/>
177      </xsl:otherwise>
178    </xsl:choose>
179  </xsl:variable>
180  <xsl:variable name="topRightLatitude">
181    <xsl:choose>
182      <xsl:when test="/rules/bounds">
183        <xsl:value-of select="/rules/bounds/@maxlat"/>
184      </xsl:when>
185      <xsl:when test="$data/osm/bounds">
186        <xsl:value-of select="$data/osm/bounds/@request_maxlat"/>
187      </xsl:when>
188      <xsl:otherwise>
189        <xsl:value-of select="$trlat"/>
190      </xsl:otherwise>
191    </xsl:choose>
192  </xsl:variable>
193  <xsl:variable name="topRightLongitude">
194    <xsl:choose>
195      <xsl:when test="/rules/bounds">
196        <xsl:value-of select="/rules/bounds/@maxlon"/>
197      </xsl:when>
198      <xsl:when test="$data/osm/bounds">
199        <xsl:value-of select="$data/osm/bounds/@request_maxlon"/>
200      </xsl:when>
201      <xsl:otherwise>
202        <xsl:value-of select="$trlon"/>
203      </xsl:otherwise>
204    </xsl:choose>
205  </xsl:variable>
206
207  <!-- Derive the latitude of the middle of the map -->
208  <xsl:variable name="middleLatitude" select="($topRightLatitude + $bottomLeftLatitude) div 2.0"/>
209  <!--woohoo lets do trigonometry in xslt -->
210  <!--convert latitude to radians -->
211  <xsl:variable name="latr" select="$middleLatitude * 3.1415926 div 180.0"/>
212  <!--taylor series: two terms is 1% error at lat<68 and 10% error lat<83. we probably need polar projection by then -->
213  <xsl:variable name="coslat" select="1 - ($latr * $latr) div 2 + ($latr * $latr * $latr * $latr) div 24"/>
214  <xsl:variable name="projection" select="1 div $coslat"/>
215
216  <xsl:variable name="dataWidth" select="(number($topRightLongitude)-number($bottomLeftLongitude))*10000*$scale"/>
217  <xsl:variable name="dataHeight" select="(number($topRightLatitude)-number($bottomLeftLatitude))*10000*$scale*$projection"/>
218  <xsl:variable name="km" select="(0.0089928*$scale*10000*$projection)"/>
219
220  <xsl:variable name="documentWidth">
221    <xsl:choose>
222      <xsl:when test="$dataWidth &gt; (number(/rules/@minimumMapWidth) * $km)">
223        <xsl:value-of select="$dataWidth"/>
224      </xsl:when>
225      <xsl:otherwise>
226        <xsl:value-of select="number(/rules/@minimumMapWidth) * $km"/>
227      </xsl:otherwise>
228    </xsl:choose>
229  </xsl:variable>
230
231  <xsl:variable name="documentHeight">
232    <xsl:choose>
233      <xsl:when test="$dataHeight &gt; (number(/rules/@minimumMapHeight) * $km)">
234        <xsl:value-of select="$dataHeight"/>
235      </xsl:when>
236      <xsl:otherwise>
237        <xsl:value-of select="number(/rules/@minimumMapHeight) * $km"/>
238      </xsl:otherwise>
239    </xsl:choose>
240  </xsl:variable>
241
242  <xsl:variable name="width" select="($documentWidth div 2) + ($dataWidth div 2)"/>
243  <xsl:variable name="height" select="($documentHeight div 2) + ($dataHeight div 2)"/>
244
245
246
247  <!-- Main template -->
248  <xsl:template match="/rules">
249
250    <!-- Include an external css stylesheet if one was specified in the rules file -->
251    <xsl:if test="@xml-stylesheet">
252      <xsl:processing-instruction name="xml-stylesheet">
253        href="<xsl:value-of select="@xml-stylesheet"/>" type="text/css"
254      </xsl:processing-instruction>
255    </xsl:if>
256
257    <xsl:variable name="svgWidth" select="$documentWidth + $extraWidth"/>
258    <xsl:variable name="svgHeight" select="$documentHeight + $marginaliaTopHeight + $marginaliaBottomHeight"/>
259
260    <svg id="main"
261  version="1.1"
262  baseProfile="{$svgBaseProfile}"
263  width="{$svgWidth}px"
264  height="{$svgHeight}px"
265  viewBox="{-$extraWidth div 2} {-$extraHeight div 2} {$svgWidth} {$svgHeight}">
266      <xsl:if test="/rules/@interactive='yes'">
267        <xsl:attribute name="onscroll">fnOnScroll(evt)</xsl:attribute>
268        <xsl:attribute name="onzoom">fnOnZoom(evt)</xsl:attribute>
269        <xsl:attribute name="onload">fnOnLoad(evt)</xsl:attribute>
270        <xsl:attribute name="onmousedown">fnOnMouseDown(evt)</xsl:attribute>
271        <xsl:attribute name="onmousemove">fnOnMouseMove(evt)</xsl:attribute>
272        <xsl:attribute name="onmouseup">fnOnMouseUp(evt)</xsl:attribute>
273      </xsl:if>
274
275      <xsl:call-template name="metadata"/>
276
277      <!-- Include javaScript functions for all the dynamic stuff -->
278      <xsl:if test="/rules/@interactive='yes'">
279        <xsl:call-template name="javaScript"/>
280      </xsl:if>
281
282
283      <defs id="defs-rulefile">
284        <!-- Get any <defs> and styles from the rules file -->
285        <xsl:copy-of select="defs/*"/>
286      </defs>
287
288
289      <xsl:if test="$symbolsDir != ''">
290        <!-- Get all symbols mentioned in the rules file from the symbolsDir -->
291        <defs id="defs-symbols">
292          <xsl:for-each select="/rules//symbol/@ref">
293            <xsl:copy-of select="document(concat($symbolsDir,'/', ., '.svg'))/svg:svg/svg:defs/svg:symbol"/>
294          </xsl:for-each>
295        </defs>
296      </xsl:if>
297
298      <!-- Pre-generate named path definitions for all ways -->
299      <xsl:variable name="allWays" select="$data/osm/way"/>
300      <defs id="defs-ways">
301        <xsl:for-each select="$allWays">
302          <xsl:call-template name="generateWayPaths"/>
303        </xsl:for-each>
304      </defs>
305
306      <!-- Clipping rectangle for map -->
307      <clipPath id="map-clipping">
308        <rect id="map-clipping-rect" x="0px" y="0px" height="{$documentHeight}px" width="{$documentWidth}px"/>
309      </clipPath>
310
311      <g id="map" clip-path="url(#map-clipping)" inkscape:groupmode="layer" inkscape:label="Map" transform="translate(0,{$marginaliaTopHeight})">
312        <!-- Draw a nice background layer -->
313        <rect id="background" x="0px" y="0px" height="{$documentHeight}px" width="{$documentWidth}px" class="map-background"/>
314
315        <!-- Process all the rules drawing all map features -->
316        <xsl:call-template name="processRules"/>
317      </g>
318
319      <!-- Draw map decoration -->
320      <g id="map-decoration" inkscape:groupmode="layer" inkscape:label="Map decoration" transform="translate(0,{$marginaliaTopHeight})">
321        <!-- Draw a grid if required -->
322        <xsl:if test="$showGrid='yes'">
323          <xsl:call-template name="drawGrid"/>
324        </xsl:if>
325
326        <!-- Draw a border if required -->
327        <xsl:if test="$showBorder='yes'">
328          <xsl:call-template name="drawBorder"/>
329        </xsl:if>
330      </g>
331
332      <!-- Draw map marginalia -->
333      <xsl:if test="($title != '') or ($showScale = 'yes') or ($showLicense = 'yes')">
334        <g id="marginalia" inkscape:groupmode="layer" inkscape:label="Marginalia">
335          <!-- Draw the title -->
336          <xsl:if test="$title!=''">
337            <xsl:call-template name="drawTitle">
338              <xsl:with-param name="title" select="$title"/>
339            </xsl:call-template>
340          </xsl:if>
341
342          <xsl:if test="($showScale = 'yes') or ($showLicense = 'yes')">
343            <g id="marginalia-bottom" inkscape:groupmode="layer" inkscape:label="Marginalia (Bottom)" transform="translate(0,{$marginaliaTopHeight})">
344              <!-- Draw background for marginalia at bottom -->
345              <rect id="marginalia-background" x="0px" y="{$documentHeight + 5}px" height="40px" width="{$documentWidth}px" class="map-marginalia-background"/>
346
347              <!-- Draw the scale in the bottom left corner -->
348              <xsl:if test="$showScale='yes'">
349                <xsl:call-template name="drawScale"/>
350              </xsl:if>
351
352              <!-- Draw Creative commons license -->
353              <xsl:if test="$showLicense='yes'">
354                <xsl:call-template name="in-image-license">
355                  <xsl:with-param name="dx" select="$documentWidth"/>
356                  <xsl:with-param name="dy" select="$documentHeight"/>
357                </xsl:call-template>
358              </xsl:if>
359            </g>
360          </xsl:if>
361        </g>
362      </xsl:if>
363
364      <!-- Draw labels and controls that are in a static position -->
365      <g id="staticElements" transform="scale(1) translate(0,0)">
366        <!-- Draw the +/- zoom controls -->
367        <xsl:if test="/rules/@interactive='yes'">
368          <xsl:call-template name="zoomControl"/>
369        </xsl:if>
370      </g>
371    </svg>
372
373  </xsl:template>
374
375  <!-- Path Fragment Drawing -->
376  <xsl:template name="drawPath">
377    <xsl:param name='instruction' />
378    <xsl:param name='pathId'/>
379    <xsl:param name='extraClasses'/>
380
381    <xsl:variable name="maskId" select="concat('mask_',$pathId)"/>
382
383    <xsl:call-template name='generateMask'>
384      <xsl:with-param name='instruction' select='$instruction'/>
385      <xsl:with-param name='pathId' select='$pathId'/>
386      <xsl:with-param name='maskId' select='$maskId'/>
387    </xsl:call-template>
388
389    <use xlink:href="#{$pathId}">
390      <!-- Copy all attributes from instruction -->
391      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes" />
392      <!-- Add in any extra classes -->
393      <xsl:attribute name="class">
394        <xsl:value-of select='$instruction/@class'/>
395        <xsl:text> </xsl:text>
396        <xsl:value-of select="$extraClasses"/>
397      </xsl:attribute>
398      <!-- If there is a mask class then include the mask attribute -->
399      <xsl:if test='$instruction/@mask-class'>
400        <xsl:attribute name="mask">
401          url(#<xsl:value-of select="$maskId"/>)
402        </xsl:attribute>
403      </xsl:if>
404      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
405    </use>
406  </xsl:template>
407
408
409  <xsl:template name='generateMask'>
410    <xsl:param name='instruction' />
411    <xsl:param name='pathId'/>
412    <xsl:param name='maskId'/>
413
414    <!-- If the instruction has a mask class -->
415    <xsl:if test='$instruction/@mask-class'>
416      <mask id="{$maskId}" maskUnits="userSpaceOnUse">
417        <use xlink:href="#{$pathId}" class="{$instruction/@mask-class} osmarender-mask-black" />
418        <!-- Required for Inkscape bug -->
419        <use xlink:href="#{$pathId}" class="{$instruction/@class} osmarender-mask-white" />
420        <use xlink:href="#{$pathId}" class="{$instruction/@mask-class} osmarender-mask-black" />
421      </mask>
422    </xsl:if>
423  </xsl:template>
424
425
426
427  <!-- Draw a line for the current <way> element using the formatting of the current <line> instruction -->
428  <xsl:template name="drawWay">
429    <xsl:param name="instruction"/>
430    <xsl:param name="way"/>
431    <!-- The current way element if applicable -->
432    <xsl:param name="layer"/>
433
434    <xsl:choose>
435      <xsl:when test="$instruction/@smart-linecap='no'">
436        <xsl:call-template name='drawPath'>
437          <xsl:with-param name='pathId' select="concat('way_normal_',$way/@id)"/>
438          <xsl:with-param name='instruction' select='$instruction'/>
439        </xsl:call-template>
440      </xsl:when>
441      <xsl:otherwise>
442        <xsl:call-template name="drawWayWithSmartLinecaps">
443          <xsl:with-param name="instruction" select="$instruction"/>
444          <xsl:with-param name="way" select="$way"/>
445          <xsl:with-param name="layer" select="$layer"/>
446        </xsl:call-template>
447      </xsl:otherwise>
448    </xsl:choose>
449  </xsl:template>
450
451
452  <xsl:template name="drawWayWithSmartLinecaps">
453    <xsl:param name="instruction"/>
454    <xsl:param name="way"/>
455    <!-- The current way element if applicable -->
456    <xsl:param name="layer"/>
457
458    <!-- The first half of the first segment and the last half of the last segment are treated differently from the main
459                        part of the way path.  The main part is always rendered with a butt line-cap.  Each end fragement is rendered with
460                        either a round line-cap, if it connects to some other path, or with its default line-cap if it is not connected
461                        to anything.  That way, cul-de-sacs etc are terminated with round, square or butt as specified in the style for the
462                        way. -->
463
464    <!-- First draw the middle section of the way with round linejoins and butt linecaps -->
465    <xsl:if test="count($way/nd) &gt; 1">
466      <xsl:call-template name='drawPath'>
467        <xsl:with-param name='pathId' select="concat('way_mid_',$way/@id)"/>
468        <xsl:with-param name='instruction' select='$instruction'/>
469        <xsl:with-param name='extraClasses'>osmarender-stroke-linecap-butt osmarender-no-marker-start osmarender-no-marker-end</xsl:with-param>
470      </xsl:call-template>
471    </xsl:if>
472
473
474    <!-- For the first half segment in the way, count the number of segments that link to the from-node of this segment.
475                        Also count links where the layer tag is less than the layer of this way, if there are links on a lower layer then
476                        we can safely draw a butt line-cap because the lower layer will already have a round line-cap. -->
477    <!-- Process the first segment in the way -->
478    <xsl:variable name="firstNode" select="key('nodeById',$way/nd[1]/@ref)"/>
479
480    <!-- Count the number of segments connecting to the from node. If there is only one (the current segment) then draw a default line.  -->
481    <xsl:variable name="firstNodeConnectionCount" select="count(key('wayByNode',$firstNode/@id))" />
482
483    <!-- Count the number of connectors at a layer lower than the current layer -->
484    <xsl:variable name="firstNodeLowerLayerConnectionCount" select="
485                        count(key('wayByNode',$firstNode/@id)/tag[@k='layer' and @v &lt; $layer]) +
486                        count(key('wayByNode',$firstNode/@id)[count(tag[@k='layer'])=0 and $layer &gt; 0])
487                        " />
488    <xsl:choose>
489      <xsl:when test="$firstNodeConnectionCount=1">
490        <xsl:call-template name='drawPath'>
491          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
492          <xsl:with-param name='instruction' select='$instruction'/>
493          <xsl:with-param name="extraClasses">osmarender-no-marker-end</xsl:with-param>
494        </xsl:call-template>
495      </xsl:when>
496      <xsl:when test="$firstNodeLowerLayerConnectionCount>0">
497        <xsl:call-template name='drawPath'>
498          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
499          <xsl:with-param name='instruction' select='$instruction'/>
500          <xsl:with-param name="extraClasses">osmarender-stroke-linecap-butt osmarender-no-marker-end</xsl:with-param>
501        </xsl:call-template>
502      </xsl:when>
503      <xsl:otherwise>
504        <xsl:call-template name='drawPath'>
505          <xsl:with-param name='pathId' select="concat('way_start_',$way/@id)"/>
506          <xsl:with-param name='instruction' select='$instruction'/>
507          <xsl:with-param name="extraClasses">osmarender-stroke-linecap-round osmarender-no-marker-end</xsl:with-param>
508        </xsl:call-template>
509      </xsl:otherwise>
510
511    </xsl:choose>
512
513
514    <!-- Process the last segment in the way -->
515    <xsl:variable name="lastNode" select="key('nodeById',$way/nd[last()]/@ref)"/>
516
517    <!-- Count the number of segments connecting to the last node. If there is only one (the current segment) then draw
518                     a default line.  -->
519    <xsl:variable name="lastNodeConnectionCount" select="count(key('wayByNode',$lastNode/@id))" />
520    <!-- Count the number of connectors at a layer lower than the current layer -->
521    <xsl:variable name="lastNodeLowerLayerConnectionCount" select="
522                        count(key('wayByNode',$lastNode/@id)/tag[@k='layer' and @v &lt; $layer]) +
523                        count(key('wayByNode',$lastNode/@id)[count(tag[@k='layer'])=0 and $layer &gt; 0])
524                        " />
525
526
527    <xsl:choose>
528      <xsl:when test="$lastNodeConnectionCount=1">
529        <xsl:call-template name='drawPath'>
530          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
531          <xsl:with-param name='instruction' select='$instruction'/>
532          <xsl:with-param name="extraClasses">osmarender-no-marker-start</xsl:with-param>
533        </xsl:call-template>
534      </xsl:when>
535      <xsl:when test="$lastNodeLowerLayerConnectionCount>0">
536        <xsl:call-template name='drawPath'>
537          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
538          <xsl:with-param name='instruction' select='$instruction'/>
539          <xsl:with-param name="extraClasses">osmarender-stroke-linecap-butt osmarender-no-marker-start</xsl:with-param>
540        </xsl:call-template>
541      </xsl:when>
542      <xsl:otherwise>
543        <xsl:call-template name='drawPath'>
544          <xsl:with-param name='pathId' select="concat('way_end_',$way/@id)"/>
545          <xsl:with-param name='instruction' select='$instruction'/>
546          <xsl:with-param name="extraClasses">osmarender-stroke-linecap-round osmarender-no-marker-start</xsl:with-param>
547        </xsl:call-template>
548      </xsl:otherwise>
549
550    </xsl:choose>
551
552  </xsl:template>
553
554
555  <!-- Draw a circle for the current <node> element using the formatting of the current <circle> instruction -->
556  <xsl:template name="drawCircle">
557    <xsl:param name="instruction"/>
558
559    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
560    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
561
562    <circle cx="{$x}" cy="{$y}">
563      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
564      <!-- Copy all the svg attributes from the <circle> instruction -->
565    </circle>
566
567  </xsl:template>
568
569
570  <!-- Draw a symbol for the current <node> element using the formatting of the current <symbol> instruction -->
571  <xsl:template name="drawSymbol">
572    <xsl:param name="instruction"/>
573
574    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
575    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
576
577    <g transform="translate({$x},{$y}) scale({$symbolScale})">
578      <use>
579        <xsl:if test="$instruction/@ref">
580          <xsl:attribute name="xlink:href">
581            <xsl:value-of select="concat('#symbol-', $instruction/@ref)"/>
582          </xsl:attribute>
583        </xsl:if>
584        <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
585        <!-- Copy all the attributes from the <symbol> instruction -->
586      </use>
587    </g>
588  </xsl:template>
589
590
591  <!-- Render the appropriate attribute of the current <node> element using the formatting of the current <text> instruction -->
592  <xsl:template name="renderText">
593    <xsl:param name="instruction"/>
594
595    <xsl:variable name="x" select="($width)-((($topRightLongitude)-(@lon))*10000*$scale)"/>
596    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-(@lat))*10000*$scale*$projection)"/>
597
598    <text>
599      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
600      <xsl:attribute name="x">
601        <xsl:value-of select="$x"/>
602      </xsl:attribute>
603      <xsl:attribute name="y">
604        <xsl:value-of select="$y"/>
605      </xsl:attribute>
606      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
607      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
608    </text>
609  </xsl:template>
610
611
612  <!-- Render the appropriate attribute of the current <segment> element using the formatting of the current <textPath> instruction -->
613  <xsl:template name="renderTextPath">
614    <xsl:param name="instruction"/>
615    <xsl:param name="pathId"/>
616    <xsl:param name="pathDirection"/>
617    <xsl:param name='text'/>
618
619    <xsl:variable name='pathLengthSquared'>
620      <xsl:call-template name='getPathLength'>
621        <xsl:with-param name='pathLengthMultiplier'>
622          <!-- This factor is used to adjust the path-length for comparison with text along a path to determine whether it will fit. -->
623          <xsl:choose>
624            <xsl:when test='$instruction/@textAttenuation'>
625              <xsl:value-of select='$instruction/@textAttenuation'/>
626            </xsl:when>
627            <xsl:when test='string($textAttenuation)'>
628              <xsl:value-of select='$textAttenuation'/>
629            </xsl:when>
630            <xsl:otherwise>99999999</xsl:otherwise>
631          </xsl:choose>
632        </xsl:with-param>
633        <xsl:with-param name='nodes' select='nd'/>
634      </xsl:call-template>
635    </xsl:variable>
636
637    <xsl:variable name='textLength' select='string-length($text)' />
638    <xsl:variable name='textLengthSquared100' select='($textLength)*($textLength)' />
639    <xsl:variable name='textLengthSquared90' select='($textLength *.9)*($textLength*.9)' />
640    <xsl:variable name='textLengthSquared80' select='($textLength *.8)*($textLength*.8)' />
641    <xsl:variable name='textLengthSquared70' select='($textLength *.7)*($textLength*.7)' />
642
643    <xsl:choose>
644      <xsl:when test='($pathLengthSquared) > $textLengthSquared100'>
645        <text>
646          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
647          <textPath xlink:href="#{$pathId}">
648            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
649            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
650            <xsl:value-of select="$text"/>
651          </textPath>
652        </text>
653      </xsl:when>
654      <xsl:when test='($pathLengthSquared) > ($textLengthSquared90)'>
655        <text>
656          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
657          <textPath xlink:href="#{$pathId}">
658            <xsl:attribute name='font-size'>90%</xsl:attribute>
659            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
660            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
661            <xsl:value-of select="$text"/>
662          </textPath>
663        </text>
664      </xsl:when>
665      <xsl:when test='($pathLengthSquared) > ($textLengthSquared80)'>
666        <text>
667          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
668          <textPath xlink:href="#{$pathId}">
669            <xsl:attribute name='font-size'>80%</xsl:attribute>
670            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
671            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
672            <xsl:value-of select="$text"/>
673          </textPath>
674        </text>
675      </xsl:when>
676      <xsl:when test='($pathLengthSquared) > ($textLengthSquared70)'>
677        <text>
678          <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-text"/>
679          <textPath xlink:href="#{$pathId}">
680            <xsl:attribute name='font-size'>70%</xsl:attribute>
681            <xsl:apply-templates select="$instruction/@*" mode="renderTextPath-textPath"/>
682            <xsl:call-template name="getSvgAttributesFromOsmTags"/>
683            <xsl:value-of select="$text"/>
684          </textPath>
685        </text>
686      </xsl:when>
687      <xsl:otherwise />
688      <!-- Otherwise don't render the text -->
689    </xsl:choose>
690  </xsl:template>
691
692
693  <xsl:template name='getPathLength'>
694    <xsl:param name='sumLon' select='number("0")' />
695    <!-- initialise sum to zero -->
696    <xsl:param name='sumLat' select='number("0")' />
697    <!-- initialise sum to zero -->
698    <xsl:param name='nodes'/>
699    <xsl:param name='pathLengthMultiplier'/>
700    <xsl:choose>
701      <xsl:when test='$nodes[1] and $nodes[2]'>
702        <xsl:variable name='fromNode' select='key("nodeById",$nodes[1]/@ref)'/>
703        <xsl:variable name='toNode' select='key("nodeById",$nodes[2]/@ref)'/>
704        <xsl:variable name='lengthLon' select='($fromNode/@lon)-($toNode/@lon)'/>
705        <xsl:variable name='absLengthLon'>
706          <xsl:choose>
707            <xsl:when test='$lengthLon &lt; 0'>
708              <xsl:value-of select='$lengthLon * -1'/>
709            </xsl:when>
710            <xsl:otherwise>
711              <xsl:value-of select='$lengthLon'/>
712            </xsl:otherwise>
713          </xsl:choose>
714        </xsl:variable>
715        <xsl:variable name='lengthLat' select='($fromNode/@lat)-($toNode/@lat)'/>
716        <xsl:variable name='absLengthLat'>
717          <xsl:choose>
718            <xsl:when test='$lengthLat &lt; 0'>
719              <xsl:value-of select='$lengthLat * -1'/>
720            </xsl:when>
721            <xsl:otherwise>
722              <xsl:value-of select='$lengthLat'/>
723            </xsl:otherwise>
724          </xsl:choose>
725        </xsl:variable>
726        <xsl:call-template name='getPathLength'>
727          <xsl:with-param name='sumLon' select='$sumLon+$absLengthLon'/>
728          <xsl:with-param name='sumLat' select='$sumLat+$absLengthLat'/>
729          <xsl:with-param name='nodes' select='$nodes[position()!=1]'/>
730          <xsl:with-param name='pathLengthMultiplier' select='$pathLengthMultiplier'/>
731        </xsl:call-template>
732      </xsl:when>
733      <xsl:otherwise>
734        <!-- Add the square of the total horizontal length to the square of the total vertical length to get the square of
735                                     the total way length.  We don't have a sqrt() function so leave it squared.
736                                     Multiply by 1,000 so that we are usually dealing with a values greater than 1.  Squares of values between 0 and 1
737                                     are smaller and so not very useful.
738                                     Multiply the latitude component by $projection to adjust for Mercator projection issues.
739                                     -->
740        <xsl:value-of select='(
741                                        (($sumLon*1000*$pathLengthMultiplier)*($sumLon*1000*$pathLengthMultiplier))+
742                                        (($sumLat*1000*$pathLengthMultiplier*$projection)*($sumLat*1000*$pathLengthMultiplier*$projection))
743                                        )'/>
744      </xsl:otherwise>
745    </xsl:choose>
746  </xsl:template>
747
748
749  <!-- Suppress the following attributes, allow everything else -->
750  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength|@k" mode="renderTextPath-text" />
751
752  <xsl:template match="@*" mode="renderTextPath-text">
753    <xsl:copy/>
754  </xsl:template>
755
756
757  <!-- Allow the following attributes, suppress everything else -->
758  <xsl:template match="@startOffset|@method|@spacing|@lengthAdjust|@textLength" mode="renderTextPath-textPath">
759    <xsl:copy/>
760  </xsl:template>
761
762  <xsl:template match="@*" mode="renderTextPath-textPath" />
763
764
765  <!-- If there are any tags like <tag k="svg:font-size" v="5"/> then add these as attributes of the svg output -->
766  <xsl:template name="getSvgAttributesFromOsmTags">
767    <xsl:for-each select="tag[contains(@k,'svg:')]">
768      <xsl:attribute name="{substring-after(@k,'svg:')}">
769        <xsl:value-of select="@v"/>
770      </xsl:attribute>
771    </xsl:for-each>
772  </xsl:template>
773
774
775  <xsl:template name="renderArea">
776    <xsl:param name="instruction"/>
777    <xsl:param name="pathId"/>
778
779    <use xlink:href="#{$pathId}">
780      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
781    </use>
782  </xsl:template>
783
784
785  <!-- Templates to process line, circle, text, etc. instructions -->
786  <!-- Each template is passed a variable containing the set of elements that need to
787         be processed.  The set of elements is already determined by the rules, so
788         these templates don't need to know anything about the rules context they are in. -->
789
790  <!-- Process a <line> instruction -->
791  <xsl:template match="line">
792    <xsl:param name="elements"/>
793    <xsl:param name="layer"/>
794
795    <!-- This is the instruction that is currently being processed -->
796    <xsl:variable name="instruction" select="."/>
797
798    <g>
799      <xsl:apply-templates select="@*" mode="copyAttributes" />
800      <!-- Add all the svg attributes of the <line> instruction to the <g> element -->
801
802      <!-- For each way -->
803      <xsl:apply-templates select="$elements" mode="line">
804        <xsl:with-param name="instruction" select="$instruction"/>
805        <xsl:with-param name="layer" select="$layer"/>
806      </xsl:apply-templates>
807
808    </g>
809  </xsl:template>
810
811
812  <!-- Suppress output of any unhandled elements -->
813  <xsl:template match="*" mode="line"/>
814
815
816  <!-- Draw lines for a way  -->
817  <xsl:template match="way" mode="line">
818    <xsl:param name="instruction"/>
819    <xsl:param name="layer"/>
820
821    <!-- The current <way> element -->
822    <xsl:variable name="way" select="."/>
823
824    <!-- DODI: !!!WORKAROUND!!! skip one node ways-->
825    <xsl:if test="count($way/nd) &gt; 1">
826      <xsl:call-template name="drawWay">
827        <xsl:with-param name="instruction" select="$instruction"/>
828        <xsl:with-param name="way" select="$way"/>
829        <xsl:with-param name="layer" select="$layer"/>
830      </xsl:call-template>
831    </xsl:if >
832  </xsl:template>
833
834
835  <!-- Process an <area> instruction -->
836  <xsl:template match="area">
837    <xsl:param name="elements"/>
838
839    <!-- This is the instruction that is currently being processed -->
840    <xsl:variable name="instruction" select="."/>
841
842    <g>
843      <xsl:apply-templates select="@*" mode="copyAttributes"/>
844      <!-- Add all the svg attributes of the <line> instruction to the <g> element -->
845
846      <!-- For each way -->
847      <xsl:apply-templates select="$elements" mode="area">
848        <xsl:with-param name="instruction" select="$instruction"/>
849      </xsl:apply-templates>
850    </g>
851  </xsl:template>
852
853
854  <!-- Discard anything that is not matched by a more specific template -->
855  <xsl:template match="*" mode="area"/>
856
857
858  <!-- Draw area for a <way> -->
859  <xsl:template match="way" mode="area">
860    <xsl:param name="instruction"/>
861
862    <!-- DODI:  removed because duplicate definition generated if area referenced 2 or more times -->
863    <!-- DODI:  reenabled because of "duplicate point detection in lines2curves.pl " -->
864    <!-- <xsl:call-template name="generateAreaPath"/> -->
865
866    <xsl:variable name="pathArea">
867      <xsl:call-template name="generateAreaPath"/>
868    </xsl:variable>
869
870    <!-- DODI: do now draw empty ways/areas-->
871    <xsl:if test ="$pathArea!=''">
872      <path id="area_{@id}" d="{$pathArea}"/>
873      <xsl:call-template name="renderArea">
874        <xsl:with-param name="instruction" select="$instruction"/>
875        <xsl:with-param name="pathId" select="concat('area_',@id)"/>
876      </xsl:call-template>
877    </xsl:if>
878  </xsl:template>
879
880
881  <!-- Process <circle> instruction -->
882  <xsl:template match="circle">
883    <xsl:param name="elements"/>
884
885    <!-- This is the instruction that is currently being processed -->
886    <xsl:variable name="instruction" select="."/>
887
888    <xsl:for-each select="$elements[name()='node']">
889      <xsl:call-template name="drawCircle">
890        <xsl:with-param name="instruction" select="$instruction"/>
891      </xsl:call-template>
892    </xsl:for-each>
893  </xsl:template>
894
895
896  <!-- Process a <symbol> instruction -->
897  <xsl:template match="symbol">
898    <xsl:param name="elements"/>
899
900    <!-- This is the instruction that is currently being processed -->
901    <xsl:variable name="instruction" select="."/>
902
903    <xsl:for-each select="$elements[name()='node']">
904      <xsl:call-template name="drawSymbol">
905        <xsl:with-param name="instruction" select="$instruction"/>
906      </xsl:call-template>
907    </xsl:for-each>
908
909  </xsl:template>
910
911
912  <!-- Process an <areaText> instruction -->
913  <xsl:template match="areaText">
914    <xsl:param name="elements"/>
915
916    <!-- This is the instruction that is currently being processed -->
917    <xsl:variable name="instruction" select="."/>
918
919    <!-- Select all <way> elements that have a key that matches the k attribute of the text instruction -->
920    <xsl:apply-templates select="$elements[name()='way'][tag[@k=$instruction/@k]]" mode="areaTextPath">
921      <xsl:with-param name="instruction" select="$instruction"/>
922    </xsl:apply-templates>
923  </xsl:template>
924
925
926  <xsl:template match="*" mode="areaTextPath"/>
927
928
929  <xsl:template match="way" mode="areaTextPath">
930    <xsl:param name="instruction"/>
931
932    <!-- The current <way> element -->
933    <xsl:variable name="way" select="."/>
934
935    <xsl:call-template name="renderAreaText">
936      <xsl:with-param name="instruction" select="$instruction"/>
937      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
938    </xsl:call-template>
939
940  </xsl:template>
941
942
943  <xsl:template name="renderAreaText">
944    <xsl:param name="instruction"/>
945
946    <xsl:variable name='left'>
947      <xsl:call-template name='areaExtentLeft'>
948        <xsl:with-param name='nd' select='./nd[1]'/>
949        <!-- First node -->
950        <xsl:with-param name='left' select='key("nodeById",./nd[1]/@ref)/@lon'/>
951        <!-- Longitude of first node -->
952      </xsl:call-template>
953    </xsl:variable>
954
955    <xsl:variable name='right'>
956      <xsl:call-template name='areaExtentRight'>
957        <xsl:with-param name='nd' select='./nd[1]'/>
958        <!-- First node -->
959        <xsl:with-param name='right' select='key("nodeById",./nd[1]/@ref)/@lon'/>
960        <!-- Longitude of first node -->
961      </xsl:call-template>
962    </xsl:variable>
963
964    <xsl:variable name='top'>
965      <xsl:call-template name='areaExtentTop'>
966        <xsl:with-param name='nd' select='./nd[1]'/>
967        <!-- First node -->
968        <xsl:with-param name='top' select='key("nodeById",./nd[1]/@ref)/@lat'/>
969        <!-- Latitude of first node -->
970      </xsl:call-template>
971    </xsl:variable>
972
973    <xsl:variable name='bottom'>
974      <xsl:call-template name='areaExtentBottom'>
975        <xsl:with-param name='nd' select='./nd[1]'/>
976        <!-- First node -->
977        <xsl:with-param name='bottom' select='key("nodeById",./nd[1]/@ref)/@lat'/>
978        <!-- Latitude of first node -->
979      </xsl:call-template>
980    </xsl:variable>
981
982    <xsl:variable name='midLon'>
983      <xsl:value-of select='$left+(($right - $left) div 2)'/>
984    </xsl:variable>
985    <xsl:variable name='midLat'>
986      <xsl:value-of select='$bottom+(($top - $bottom) div 2)'/>
987    </xsl:variable>
988
989    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($midLon))*10000*$scale)"/>
990    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($midLat))*10000*$scale*$projection)"/>
991
992    <text>
993      <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
994      <xsl:attribute name="x">
995        <xsl:value-of select="$x"/>
996      </xsl:attribute>
997      <xsl:attribute name="y">
998        <xsl:value-of select="$y"/>
999      </xsl:attribute>
1000      <xsl:call-template name="getSvgAttributesFromOsmTags"/>
1001      <xsl:value-of select="tag[@k=$instruction/@k]/@v"/>
1002    </text>
1003  </xsl:template>
1004
1005  <!-- Process an <areaSymbol> instruction -->
1006  <xsl:template match="areaSymbol">
1007    <xsl:param name="elements"/>
1008
1009    <!-- This is the instruction that is currently being processed -->
1010    <xsl:variable name="instruction" select="."/>
1011
1012    <!-- Select all <way> elements -->
1013    <xsl:apply-templates select="$elements[name()='way']" mode="areaSymbolPath">
1014      <xsl:with-param name="instruction" select="$instruction"/>
1015    </xsl:apply-templates>
1016  </xsl:template>
1017
1018
1019  <xsl:template match="*" mode="areaSymbolPath"/>
1020
1021
1022  <xsl:template match="way" mode="areaSymbolPath">
1023    <xsl:param name="instruction"/>
1024
1025    <!-- The current <way> element -->
1026    <xsl:variable name="way" select="."/>
1027
1028    <xsl:call-template name="renderAreaSymbol">
1029      <xsl:with-param name="instruction" select="$instruction"/>
1030      <xsl:with-param name="pathId" select="concat('way_normal_',@id)"/>
1031    </xsl:call-template>
1032
1033  </xsl:template>
1034
1035
1036  <xsl:template name="renderAreaSymbol">
1037    <xsl:param name="instruction"/>
1038
1039    <xsl:variable name='left'>
1040      <xsl:call-template name='areaExtentLeft'>
1041        <xsl:with-param name='nd' select='./nd[1]'/>
1042        <!-- First node -->
1043        <xsl:with-param name='left' select='key("nodeById",./nd[1]/@ref)/@lon'/>
1044        <!-- Longitude of first node -->
1045      </xsl:call-template>
1046    </xsl:variable>
1047
1048    <xsl:variable name='right'>
1049      <xsl:call-template name='areaExtentRight'>
1050        <xsl:with-param name='nd' select='./nd[1]'/>
1051        <!-- First node -->
1052        <xsl:with-param name='right' select='key("nodeById",./nd[1]/@ref)/@lon'/>
1053        <!-- Longitude of first node -->
1054      </xsl:call-template>
1055    </xsl:variable>
1056
1057    <xsl:variable name='top'>
1058      <xsl:call-template name='areaExtentTop'>
1059        <xsl:with-param name='nd' select='./nd[1]'/>
1060        <!-- First node -->
1061        <xsl:with-param name='top' select='key("nodeById",./nd[1]/@ref)/@lat'/>
1062        <!-- Latitude of first node -->
1063      </xsl:call-template>
1064    </xsl:variable>
1065
1066    <xsl:variable name='bottom'>
1067      <xsl:call-template name='areaExtentBottom'>
1068        <xsl:with-param name='nd' select='./nd[1]'/>
1069        <!-- First node -->
1070        <xsl:with-param name='bottom' select='key("nodeById",./nd[1]/@ref)/@lat'/>
1071        <!-- Latitude of first node -->
1072      </xsl:call-template>
1073    </xsl:variable>
1074
1075    <xsl:variable name='midLon'>
1076      <xsl:value-of select='$left+(($right - $left) div 2)'/>
1077    </xsl:variable>
1078    <xsl:variable name='midLat'>
1079      <xsl:value-of select='$bottom+(($top - $bottom) div 2)'/>
1080    </xsl:variable>
1081
1082    <xsl:variable name="x" select="($width)-((($topRightLongitude)-($midLon))*10000*$scale)"/>
1083    <xsl:variable name="y" select="($height)+((($bottomLeftLatitude)-($midLat))*10000*$scale*$projection)"/>
1084
1085    <g transform="translate({$x},{$y}) scale({$symbolScale})">
1086      <use>
1087        <xsl:if test="$instruction/@ref">
1088          <xsl:attribute name="xlink:href">
1089            <xsl:value-of select="concat('#symbol-', $instruction/@ref)"/>
1090          </xsl:attribute>
1091        </xsl:if>
1092        <xsl:apply-templates select="$instruction/@*" mode="copyAttributes"/>
1093        <!-- Copy all the attributes from the <symbol> instruction -->
1094      </use>
1095    </g>
1096  </xsl:template>
1097
1098  <xsl:template name='areaExtentLeft'>
1099    <xsl:param name='nd'/>
1100    <xsl:param name='left'/>
1101
1102    <xsl:variable name='leftmostLon' select='key("nodeById",$nd/@ref)/@lon'/>
1103    <xsl:variable name='newLeft'>
1104      <xsl:choose>
1105        <xsl:when test='$left>$leftmostLon'>
1106          <xsl:value-of select='$leftmostLon'/>
1107        </xsl:when>
1108        <xsl:otherwise>
1109          <xsl:value-of select='$left'/>
1110        </xsl:otherwise>
1111      </xsl:choose>
1112    </xsl:variable>
1113
1114    <xsl:choose>
1115      <xsl:when test="$nd/following-sibling::nd[1]">
1116        <xsl:call-template name='areaExtentLeft'>
1117          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1118          <!-- next node -->
1119          <xsl:with-param name='left' select='$newLeft'/>
1120        </xsl:call-template>
1121      </xsl:when>
1122      <xsl:otherwise>
1123        <xsl:value-of select='$newLeft'/>
1124      </xsl:otherwise>
1125    </xsl:choose>
1126  </xsl:template>
1127
1128
1129  <xsl:template name='areaExtentRight'>
1130    <xsl:param name='nd'/>
1131    <xsl:param name='right'/>
1132
1133    <xsl:variable name='rightmostLon' select='key("nodeById",$nd/@ref)/@lon'/>
1134    <xsl:variable name='newRight'>
1135      <xsl:choose>
1136        <xsl:when test='$rightmostLon>$right'>
1137          <xsl:value-of select='$rightmostLon'/>
1138        </xsl:when>
1139        <xsl:otherwise>
1140          <xsl:value-of select='$right'/>
1141        </xsl:otherwise>
1142      </xsl:choose>
1143    </xsl:variable>
1144
1145    <xsl:choose>
1146      <xsl:when test="$nd/following-sibling::nd[1]">
1147        <xsl:call-template name='areaExtentRight'>
1148          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1149          <!-- next node -->
1150          <xsl:with-param name='right' select='$newRight'/>
1151        </xsl:call-template>
1152      </xsl:when>
1153      <xsl:otherwise>
1154        <xsl:value-of select='$newRight'/>
1155      </xsl:otherwise>
1156    </xsl:choose>
1157  </xsl:template>
1158
1159
1160  <xsl:template name='areaExtentTop'>
1161    <xsl:param name='nd'/>
1162    <xsl:param name='top'/>
1163
1164    <xsl:variable name='topmostLat' select='key("nodeById",$nd/@ref)/@lat'/>
1165    <xsl:variable name='newTop'>
1166      <xsl:choose>
1167        <xsl:when test='$top>$topmostLat'>
1168          <xsl:value-of select='$top'/>
1169        </xsl:when>
1170        <xsl:otherwise>
1171          <xsl:value-of select='$topmostLat'/>
1172        </xsl:otherwise>
1173      </xsl:choose>
1174    </xsl:variable>
1175
1176    <xsl:choose>
1177      <xsl:when test="$nd/following-sibling::nd[1]">
1178        <xsl:call-template name='areaExtentTop'>
1179          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1180          <!-- next node -->
1181          <xsl:with-param name='top' select='$newTop'/>
1182        </xsl:call-template>
1183      </xsl:when>
1184      <xsl:otherwise>
1185        <xsl:value-of select='$newTop'/>
1186      </xsl:otherwise>
1187    </xsl:choose>
1188  </xsl:template>
1189
1190
1191  <xsl:template name='areaExtentBottom'>
1192    <xsl:param name='nd'/>
1193    <xsl:param name='bottom'/>
1194
1195    <xsl:variable name='bottommostLat' select='key("nodeById",$nd/@ref)/@lat'/>
1196    <xsl:variable name='newBottom'>
1197      <xsl:choose>
1198        <xsl:when test='$bottommostLat>$bottom'>
1199          <xsl:value-of select='$bottom'/>
1200        </xsl:when>
1201        <xsl:otherwise>
1202          <xsl:value-of select='$bottommostLat'/>
1203        </xsl:otherwise>
1204      </xsl:choose>
1205    </xsl:variable>
1206
1207    <xsl:choose>
1208      <xsl:when test="$nd/following-sibling::nd[1]">
1209        <xsl:call-template name='areaExtentBottom'>
1210          <xsl:with-param name='nd' select='$nd/following-sibling::nd[1]'/>
1211          <!-- next node -->
1212          <xsl:with-param name='bottom' select='$newBottom'/>
1213        </xsl:call-template>
1214      </xsl:when>
1215      <xsl:otherwise>
1216        <xsl:value-of select='$newBottom'/>
1217      </xsl:otherwise>
1218    </xsl:choose>
1219  </xsl:template>
1220
1221  <!-- Process a <text> instruction -->
1222  <xsl:template match="text">
1223    <xsl:param name="elements"/>
1224
1225    <!-- This is the instruction that is currently being processed -->
1226    <xsl:variable name="instruction" select="."/>
1227
1228    <!-- Select all <node> elements that have a key that matches the k attribute of the text instruction -->
1229    <xsl:for-each select="$elements[name()='node'][tag[@k=$instruction/@k]]">
1230      <xsl:call-template name="renderText">
1231        <xsl:with-param name="instruction" select="$instruction"/>
1232      </xsl:call-template>
1233    </xsl:for-each>
1234
1235    <!-- Select all <way> elements -->
1236    <xsl:apply-templates select="$elements[name()='way']" mode="textPath">
1237      <xsl:with-param name="instruction" select="$instruction"/>
1238    </xsl:apply-templates>
1239  </xsl:template>
1240
1241
1242  <!-- Suppress output of any unhandled elements -->
1243  <xsl:template match="*" mode="textPath"/>
1244
1245
1246  <!-- Render textPaths for a way -->
1247  <xsl:template match="way" mode="textPath">
1248    <xsl:param name="instruction"/>
1249
1250    <!-- The current <way> element -->
1251    <xsl:variable name="way" select="."/>
1252
1253    <!-- DODI: !!!WORKAROUND!!! no text for one node ways-->
1254    <xsl:if test="count($way/nd) &gt; 1">
1255      <xsl:variable name='text'>
1256        <xsl:choose>
1257          <xsl:when test='$instruction/@k'>
1258            <xsl:value-of select='tag[@k=$instruction/@k]/@v'/>
1259          </xsl:when>
1260          <xsl:otherwise>
1261            <xsl:apply-templates select='$instruction' mode='textFormat'>
1262              <xsl:with-param name='way' select='$way'/>
1263            </xsl:apply-templates>
1264          </xsl:otherwise>
1265        </xsl:choose>
1266      </xsl:variable>
1267
1268      <xsl:if test='string($text)'>
1269
1270        <xsl:variable name="pathDirection">
1271          <xsl:choose>
1272            <!-- Manual override, reverse direction -->
1273            <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">reverse</xsl:when>
1274            <!-- Manual override, normal direction -->
1275            <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">normal</xsl:when>
1276            <!-- Automatic, reverse direction -->
1277            <xsl:when test="(key('nodeById',$way/nd[1]/@ref)/@lon &gt; key('nodeById',$way/nd[last()]/@ref)/@lon)">reverse</xsl:when>
1278            <!-- Automatic, normal direction -->
1279            <xsl:otherwise>normal</xsl:otherwise>
1280          </xsl:choose>
1281        </xsl:variable>
1282
1283        <xsl:variable name="wayPath">
1284          <xsl:choose>
1285            <!-- Normal -->
1286            <xsl:when test='$pathDirection="normal"'>
1287              <xsl:value-of select="concat('way_normal_',@id)"/>
1288            </xsl:when>
1289            <!-- Reverse -->
1290            <xsl:otherwise>
1291              <xsl:value-of select="concat('way_reverse_',@id)"/>
1292            </xsl:otherwise>
1293          </xsl:choose>
1294        </xsl:variable>
1295
1296        <xsl:call-template name="renderTextPath">
1297          <xsl:with-param name="instruction" select="$instruction"/>
1298          <xsl:with-param name="pathId" select="$wayPath"/>
1299          <xsl:with-param name="pathDirection" select="$pathDirection"/>
1300          <xsl:with-param name="text" select="$text"/>
1301        </xsl:call-template>
1302      </xsl:if>
1303    </xsl:if>
1304  </xsl:template>
1305
1306  <!-- Process extended form of text instruction -->
1307  <xsl:template match='text' mode='textFormat'>
1308    <xsl:param name='way'/>
1309
1310    <xsl:apply-templates mode='textFormat'>
1311      <xsl:with-param name='way' select='$way'/>
1312    </xsl:apply-templates>
1313  </xsl:template>
1314
1315
1316  <!-- Substitute a tag in a text instruction -->
1317  <xsl:template match='text/tag' mode='textFormat'>
1318    <xsl:param name='way'/>
1319
1320    <xsl:variable name='key' select='@k'/>
1321    <xsl:variable name='value'>
1322      <xsl:choose>
1323        <xsl:when test='$key="osm:user"'>
1324          <xsl:value-of select='$way/@user'/>
1325        </xsl:when>
1326        <xsl:when test='$key="osm:timestamp"'>
1327          <xsl:value-of select='$way/@timestamp'/>
1328        </xsl:when>
1329        <xsl:when test='$key="osm:id"'>
1330          <xsl:value-of select='$way/@id'/>
1331        </xsl:when>
1332        <xsl:otherwise>
1333          <xsl:value-of select='$way/tag[@k=$key]/@v'/>
1334        </xsl:otherwise>
1335      </xsl:choose>
1336    </xsl:variable>
1337    <xsl:choose>
1338      <xsl:when test='string($value)'>
1339        <xsl:value-of select='$value'/>
1340      </xsl:when>
1341      <xsl:otherwise>
1342        <xsl:value-of select='@default'/>
1343      </xsl:otherwise>
1344    </xsl:choose>
1345  </xsl:template>
1346
1347
1348
1349  <!-- Generate a way path for the current way element -->
1350  <xsl:template name="generateWayPaths">
1351    <!-- DODI: !!!WORKAROUND!!! skip one node ways -->
1352    <xsl:if test="count(nd) &gt; 1">
1353
1354      <!-- Generate a normal way path -->
1355      <xsl:variable name="pathWayNormal">
1356        <xsl:call-template name="generateWayPathNormal"/>
1357      </xsl:variable>
1358      <xsl:if test="$pathWayNormal!=''">
1359        <path id="way_normal_{@id}" d="{$pathWayNormal}"/>
1360      </xsl:if>
1361
1362      <!-- Generate a normal way path as area -->
1363      <!-- DODI: !!!WORKAROUND!!! added to generate "area for all ways, yes it is very dirty... but -->
1364      <!-- DODI: removed because of line2curves.pl duplicate node detection problem -->
1365      <!-- <xsl:variable name="pathArea">
1366      <xsl:call-template name="generateAreaPath"/>
1367    </xsl:variable>
1368    <path id="area_{@id}" d="{$pathArea}"/> -->
1369      <!-- Generate a reverse way path (if needed) -->
1370      <xsl:variable name="pathWayReverse">
1371        <xsl:choose>
1372          <!-- Manual override, reverse direction -->
1373          <xsl:when test="tag[@k='name_direction']/@v='-1' or tag[@k='osmarender:nameDirection']/@v='-1'">
1374            <xsl:call-template name="generateWayPathReverse"/>
1375          </xsl:when>
1376          <!-- Manual override, normal direction -->
1377          <xsl:when test="tag[@k='name_direction']/@v='1' or tag[@k='osmarender:nameDirection']/@v='1'">
1378            <!-- Generate nothing -->
1379          </xsl:when>
1380          <!-- Automatic, reverse direction -->
1381          <xsl:when test="(key('nodeById',nd[1]/@ref)/@lon &gt; key('nodeById',nd[last()]/@ref)/@lon)">
1382            <xsl:call-template name="generateWayPathReverse"/>
1383          </xsl:when>
1384        </xsl:choose>
1385      </xsl:variable>
1386      <xsl:if test="$pathWayReverse!=''">
1387        <path id="way_reverse_{@id}" d="{$pathWayReverse}"/>
1388      </xsl:if>
1389
1390      <!-- Generate the start, middle and end paths needed for smart-linecaps (TM). -->
1391      <xsl:variable name="pathWayStart">
1392        <xsl:call-template name="generatePathWayStart"/>
1393      </xsl:variable>
1394      <path id="way_start_{@id}" d="{$pathWayStart}"/>
1395
1396      <xsl:if test="count(nd) &gt; 1">
1397        <xsl:variable name="pathWayMid">
1398          <xsl:call-template name="generatePathWayMid"/>
1399        </xsl:variable>
1400        <path id="way_mid_{@id}" d="{$pathWayMid}"/>
1401      </xsl:if>
1402
1403      <xsl:variable name="pathWayEnd">
1404        <xsl:call-template name="generatePathWayEnd"/>
1405      </xsl:variable>
1406      <path id="way_end_{@id}" d="{$pathWayEnd}"/>
1407    </xsl:if >
1408  </xsl:template>
1409
1410
1411  <!-- Generate a normal way path -->
1412  <xsl:template name="generateWayPathNormal">
1413    <xsl:for-each select="nd[key('nodeById',@ref) ]">
1414      <xsl:choose>
1415        <xsl:when test="position()=1">
1416          <xsl:call-template name="moveToNode">
1417            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1418          </xsl:call-template>
1419        </xsl:when>
1420        <xsl:otherwise>
1421          <xsl:call-template name="lineToNode">
1422            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1423          </xsl:call-template>
1424        </xsl:otherwise>
1425      </xsl:choose>
1426    </xsl:for-each>
1427  </xsl:template>
1428
1429
1430  <!-- Generate a reverse way path -->
1431  <xsl:template name="generateWayPathReverse">
1432    <xsl:for-each select="nd[key('nodeById',@ref)]">
1433      <xsl:sort select="position()" data-type="number" order="descending"/>
1434      <xsl:choose>
1435        <xsl:when test="position()=1">
1436          <xsl:call-template name="moveToNode">
1437            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1438          </xsl:call-template>
1439        </xsl:when>
1440        <xsl:otherwise>
1441          <xsl:call-template name="lineToNode">
1442            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1443          </xsl:call-template>
1444        </xsl:otherwise>
1445      </xsl:choose>
1446    </xsl:for-each>
1447  </xsl:template>
1448
1449
1450  <!-- These template generates two paths, one for each end of a way.  The line to the first node is cut in two so that the join
1451         between the two paths is not at an angle.  -->
1452  <xsl:template name="generatePathWayStart">
1453    <xsl:call-template name="moveToNode">
1454      <xsl:with-param name="node" select="key('nodeById',nd[1]/@ref)"/>
1455    </xsl:call-template>
1456    <xsl:call-template name="lineToMidpointPlus">
1457      <xsl:with-param name="fromNode" select="key('nodeById',nd[1]/@ref)"/>
1458      <xsl:with-param name="toNode" select="key('nodeById',nd[2]/@ref)"/>
1459    </xsl:call-template>
1460  </xsl:template>
1461
1462
1463  <xsl:template name="generatePathWayEnd">
1464    <xsl:call-template name="moveToNode">
1465      <xsl:with-param name="node" select="key('nodeById',nd[position()=last()]/@ref)"/>
1466    </xsl:call-template>
1467    <xsl:call-template name="lineToMidpointMinus">
1468      <xsl:with-param name="fromNode" select="key('nodeById',nd[position()=(last()-1)]/@ref)"/>
1469      <xsl:with-param name="toNode" select="key('nodeById',nd[position()=last()]/@ref)"/>
1470    </xsl:call-template>
1471  </xsl:template>
1472
1473  <xsl:template name="generatePathWayMid">
1474    <xsl:for-each select="nd[key('nodeById',@ref)]">
1475      <xsl:choose>
1476        <xsl:when test="position()=1">
1477          <xsl:call-template name="moveToMidpointPlus">
1478            <xsl:with-param name="fromNode" select="key('nodeById',@ref)"/>
1479            <xsl:with-param name="toNode" select="key('nodeById',following-sibling::nd[1]/@ref)"/>
1480          </xsl:call-template>
1481        </xsl:when>
1482        <xsl:when test="position()=last()">
1483          <xsl:call-template name="lineToMidpointMinus">
1484            <xsl:with-param name="fromNode" select="key('nodeById',preceding-sibling::nd[1]/@ref)"/>
1485            <xsl:with-param name="toNode" select="key('nodeById',@ref)"/>
1486          </xsl:call-template>
1487        </xsl:when>
1488        <xsl:otherwise>
1489          <xsl:call-template name="lineToNode">
1490            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1491          </xsl:call-template>
1492        </xsl:otherwise>
1493      </xsl:choose>
1494    </xsl:for-each>
1495  </xsl:template>
1496
1497  <!-- Generate an area path for the current way or area element -->
1498  <xsl:template name="generateAreaPath">
1499    <xsl:variable name='relation' select="key('relationByWay',@id)[tag[@k='type' and @v='multipolygon']]"/>
1500    <xsl:choose>
1501      <xsl:when test='$relation'>
1502
1503        <!-- DODI: handling mulitpolygons: draw area only once
1504                   ways is a part of a multipolygon relation so we need process all members-->
1505        <xsl:variable name='firsrelationmember' select="$relation/member[@type='way'][key('wayById', @ref)][1]/@ref"/>
1506        <!-- DODI: if /me is a real first member, process all, otherwise skip it-->
1507        <xsl:if test='$firsrelationmember=@id'>
1508          <xsl:message>
1509            <xsl:value-of select='$relation/@id'/>
1510          </xsl:message>
1511          <xsl:for-each select="$relation/member[@type='way'][key('wayById', @ref)]">
1512            <xsl:call-template name='generateAreaSubPath'>
1513              <xsl:with-param name='way' select="key('wayById',@ref)"/>
1514              <xsl:with-param name='position' select="position()"/>
1515            </xsl:call-template>
1516          </xsl:for-each>
1517          <xsl:text>Z</xsl:text>
1518        </xsl:if>
1519
1520      </xsl:when>
1521      <xsl:otherwise>
1522        <xsl:call-template name='generateAreaSubPath'>
1523          <xsl:with-param name='way' select='.'/>
1524          <xsl:with-param name='position' select="'1'"/>
1525        </xsl:call-template>
1526        <xsl:text>Z</xsl:text>
1527      </xsl:otherwise>
1528    </xsl:choose>
1529  </xsl:template>
1530
1531
1532  <xsl:template name='generateAreaSubPath'>
1533    <xsl:param name='way'/>
1534    <xsl:param name='position'/>
1535
1536    <xsl:variable name='loop' select='$way/nd[1]/@ref=$way/nd[last()]/@ref'/>
1537    <xsl:message>
1538      WayId: <xsl:value-of select='$way/@id'/>
1539      Loop: <xsl:value-of select='$loop'/>
1540      Loop: <xsl:value-of select='$way/nd[1]/@ref'/>
1541      Loop: <xsl:value-of select='$way/nd[last()]/@ref'/>
1542    </xsl:message>
1543    <xsl:for-each select="$way/nd[key('nodeById',@ref)]">
1544      <xsl:choose>
1545        <xsl:when test="position()=1 and $loop">
1546          <xsl:if test='not($position=1)'>
1547            <xsl:text>Z</xsl:text>
1548          </xsl:if>
1549          <xsl:call-template name="moveToNode">
1550            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1551          </xsl:call-template>
1552        </xsl:when>
1553        <xsl:when test="$position=1 and position()=1 and not($loop=1)">
1554          <xsl:call-template name="moveToNode">
1555            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1556          </xsl:call-template>
1557        </xsl:when>
1558        <xsl:otherwise>
1559          <xsl:call-template name="lineToNode">
1560            <xsl:with-param name="node" select="key('nodeById',@ref)"/>
1561          </xsl:call-template>
1562        </xsl:otherwise>
1563      </xsl:choose>
1564    </xsl:for-each>
1565
1566
1567  </xsl:template>
1568
1569  <!-- Generate a MoveTo command for a node -->
1570  <xsl:template name="moveToNode">
1571    <xsl:param name='node' />
1572    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
1573    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
1574    <xsl:text>M</xsl:text>
1575    <xsl:value-of select="$x1"/>
1576    <xsl:text> </xsl:text>
1577    <xsl:value-of select="$y1"/>
1578  </xsl:template>
1579
1580  <!-- Generate a LineTo command for a nd -->
1581  <xsl:template name="lineToNode">
1582    <xsl:param name='node'/>
1583
1584    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($node/@lon))*10000*$scale)"/>
1585    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($node/@lat))*10000*$scale*$projection)"/>
1586    <xsl:text>L</xsl:text>
1587    <xsl:value-of select="$x1"/>
1588    <xsl:text> </xsl:text>
1589    <xsl:value-of select="$y1"/>
1590  </xsl:template>
1591
1592  <xsl:template name="lineToMidpointPlus">
1593    <xsl:param name='fromNode'/>
1594    <xsl:param name='toNode'/>
1595
1596    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1597    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1598
1599    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1600    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1601
1602    <xsl:text>L</xsl:text>
1603    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1604    <xsl:text> </xsl:text>
1605    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1606  </xsl:template>
1607
1608  <xsl:template name="lineToMidpointMinus">
1609    <xsl:param name='fromNode'/>
1610    <xsl:param name='toNode'/>
1611
1612    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1613    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1614
1615    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1616    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1617    <xsl:text>L</xsl:text>
1618    <xsl:value-of select="$x1+(($x2 - $x1) div 2.1)"/>
1619    <xsl:text> </xsl:text>
1620    <xsl:value-of select="$y1+(($y2 - $y1) div 2.1)"/>
1621  </xsl:template>
1622
1623
1624  <xsl:template name="moveToMidpointPlus">
1625    <xsl:param name='fromNode'/>
1626    <xsl:param name='toNode'/>
1627
1628    <xsl:variable name="x1" select="($width)-((($topRightLongitude)-($fromNode/@lon))*10000*$scale)"/>
1629    <xsl:variable name="y1" select="($height)+((($bottomLeftLatitude)-($fromNode/@lat))*10000*$scale*$projection)"/>
1630
1631    <xsl:variable name="x2" select="($width)-((($topRightLongitude)-($toNode/@lon))*10000*$scale)"/>
1632    <xsl:variable name="y2" select="($height)+((($bottomLeftLatitude)-($toNode/@lat))*10000*$scale*$projection)"/>
1633    <xsl:text>M</xsl:text>
1634    <xsl:value-of select="$x1+(($x2 - $x1) div 1.9)"/>
1635    <xsl:text> </xsl:text>
1636    <xsl:value-of select="$y1+(($y2 - $y1) div 1.9)"/>
1637  </xsl:template>
1638
1639  <!-- Some attribute shouldn't be copied -->
1640  <xsl:template match="@type|@ref|@scale|@smart-linecap" mode="copyAttributes" />
1641
1642  <!-- Copy all other attributes  -->
1643  <xsl:template match="@*" mode="copyAttributes">
1644    <xsl:copy/>
1645  </xsl:template>
1646
1647
1648  <!-- Rule processing engine -->
1649
1650  <!--
1651
1652                Calls all templates inside <rule> tags (including itself, if there are nested rules).
1653
1654                If the global var withOSMLayers is 'no', we don't care about layers and draw everything
1655                in one go. This is faster and is sometimes useful. For normal maps you want withOSMLayers
1656                to be 'yes', which is the default.
1657
1658        -->
1659  <xsl:template name="processRules">
1660
1661    <!-- First select all elements - exclude those marked as deleted by JOSM -->
1662    <xsl:variable name='elements' select="$data/osm/*[not(@action) or not(@action='delete')]" />
1663
1664    <xsl:choose>
1665
1666      <!-- Process all the rules, one layer at a time -->
1667      <xsl:when test="$withOSMLayers='yes'">
1668        <xsl:call-template name="processLayer">
1669          <xsl:with-param name="layer" select="'-5'"/>
1670          <xsl:with-param name="elements" select="$elements"/>
1671        </xsl:call-template>
1672        <xsl:call-template name="processLayer">
1673          <xsl:with-param name="layer" select="'-4'"/>
1674          <xsl:with-param name="elements" select="$elements"/>
1675        </xsl:call-template>
1676        <xsl:call-template name="processLayer">
1677          <xsl:with-param name="layer" select="'-3'"/>
1678          <xsl:with-param name="elements" select="$elements"/>
1679        </xsl:call-template>
1680        <xsl:call-template name="processLayer">
1681          <xsl:with-param name="layer" select="'-2'"/>
1682          <xsl:with-param name="elements" select="$elements"/>
1683        </xsl:call-template>
1684        <xsl:call-template name="processLayer">
1685          <xsl:with-param name="layer" select="'-1'"/>
1686          <xsl:with-param name="elements" select="$elements"/>
1687        </xsl:call-template>
1688        <xsl:call-template name="processLayer">
1689          <xsl:with-param name="layer" select="'0'"/>
1690          <xsl:with-param name="elements" select="$elements"/>
1691        </xsl:call-template>
1692        <xsl:call-template name="processLayer">
1693          <xsl:with-param name="layer" select="'1'"/>
1694          <xsl:with-param name="elements" select="$elements"/>
1695        </xsl:call-template>
1696        <xsl:call-template name="processLayer">
1697          <xsl:with-param name="layer" select="'2'"/>
1698          <xsl:with-param name="elements" select="$elements"/>
1699        </xsl:call-template>
1700        <xsl:call-template name="processLayer">
1701          <xsl:with-param name="layer" select="'3'"/>
1702          <xsl:with-param name="elements" select="$elements"/>
1703        </xsl:call-template>
1704        <xsl:call-template name="processLayer">
1705          <xsl:with-param name="layer" select="'4'"/>
1706          <xsl:with-param name="elements" select="$elements"/>
1707        </xsl:call-template>
1708        <xsl:call-template name="processLayer">
1709          <xsl:with-param name="layer" select="'5'"/>
1710          <xsl:with-param name="elements" select="$elements"/>
1711        </xsl:call-template>
1712      </xsl:when>
1713
1714      <!-- Process all the rules, without looking at the layers -->
1715      <xsl:otherwise>
1716        <xsl:apply-templates select="/rules/rule">
1717          <xsl:with-param name="elements" select="$elements"/>
1718          <xsl:with-param name="layer" select="'0'"/>
1719        </xsl:apply-templates>
1720      </xsl:otherwise>
1721
1722    </xsl:choose>
1723  </xsl:template>
1724
1725
1726  <xsl:template name="processLayer">
1727    <xsl:param name="layer"/>
1728    <xsl:param name="elements"/>
1729
1730    <g inkscape:groupmode="layer" id="layer{$layer}" inkscape:label="Layer {$layer}">
1731      <xsl:apply-templates select="/rules/rule">
1732        <xsl:with-param name="elements" select="$elements"/>
1733        <xsl:with-param name="layer" select="$layer"/>
1734      </xsl:apply-templates>
1735    </g>
1736  </xsl:template>
1737
1738
1739  <!-- Process a rule at a specific level -->
1740  <xsl:template match='rule'>
1741    <xsl:param name="elements"/>
1742    <xsl:param name="layer"/>
1743
1744    <!-- If the rule is for a specific layer and we are processing that layer then pass *all* elements
1745                     to the rule, otherwise just select the matching elements for this layer. -->
1746    <xsl:choose>
1747      <xsl:when test='$layer=@layer'>
1748        <xsl:call-template name="rule">
1749          <xsl:with-param name="elements" select="$elements"/>
1750          <xsl:with-param name="layer" select="$layer"/>
1751        </xsl:call-template>
1752      </xsl:when>
1753      <xsl:otherwise>
1754        <xsl:if test='not(@layer)'>
1755          <xsl:call-template name="rule">
1756            <xsl:with-param name="elements" select="$elements[
1757                                                        tag[@k='layer' and @v=$layer]
1758                                                        or ($layer='0' and count(tag[@k='layer'])=0)
1759                                                ]"/>
1760            <xsl:with-param name="layer" select="$layer"/>
1761          </xsl:call-template>
1762        </xsl:if>
1763      </xsl:otherwise>
1764    </xsl:choose>
1765  </xsl:template>
1766
1767
1768  <xsl:template name='rule'>
1769    <xsl:param name="elements"/>
1770    <xsl:param name="layer"/>
1771
1772    <!-- This is the rule currently being processed -->
1773    <xsl:variable name="rule" select="."/>
1774
1775    <!-- Make list of elements that this rule should be applied to -->
1776    <xsl:variable name="eBare">
1777      <xsl:choose>
1778        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
1779        <xsl:when test="$rule/@e">
1780          <xsl:value-of select="$rule/@e"/>
1781        </xsl:when>
1782        <xsl:otherwise>node|way</xsl:otherwise>
1783      </xsl:choose>
1784    </xsl:variable>
1785
1786    <!-- List of keys that this rule should be applied to -->
1787    <xsl:variable name="kBare" select="$rule/@k"/>
1788
1789    <!-- List of values that this rule should be applied to -->
1790    <xsl:variable name="vBare" select="$rule/@v"/>
1791    <xsl:variable name="sBare" select="$rule/@s"/>
1792
1793    <!-- Top'n'tail selectors with | for contains usage -->
1794    <xsl:variable name="e">
1795      |<xsl:value-of select="$eBare"/>|
1796    </xsl:variable>
1797    <xsl:variable name="k">
1798      |<xsl:value-of select="$kBare"/>|
1799    </xsl:variable>
1800    <xsl:variable name="v">
1801      |<xsl:value-of select="$vBare"/>|
1802    </xsl:variable>
1803    <xsl:variable name="s">
1804      |<xsl:value-of select="$sBare"/>|
1805    </xsl:variable>
1806
1807    <xsl:variable
1808      name="selectedElements"
1809      select="$elements[contains($e,concat('|',name(),'|'))
1810            or
1811            (contains($e,'|node|') and name()='way' and key('wayByNode',@id))
1812            ]"/>
1813
1814
1815    <!-- Patch $s -->
1816    <xsl:choose>
1817      <!-- way selector -->
1818      <xsl:when test="contains($s,'|way|')">
1819        <xsl:choose>
1820          <!-- every key -->
1821          <xsl:when test="contains($k,'|*|')">
1822            <xsl:choose>
1823              <!-- every key ,no value defined -->
1824              <xsl:when test="contains($v,'|~|')">
1825                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)=0]"/>
1826                <xsl:call-template name="processElements">
1827                  <xsl:with-param name="eBare" select="$eBare"/>
1828                  <xsl:with-param name="kBare" select="$kBare"/>
1829                  <xsl:with-param name="vBare" select="$vBare"/>
1830                  <xsl:with-param name="layer" select="$layer"/>
1831                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
1832                  <xsl:with-param name="rule" select="$rule"/>
1833                </xsl:call-template>
1834              </xsl:when>
1835              <!-- every key ,every value -->
1836              <xsl:when test="contains($v,'|*|')">
1837                <xsl:variable name="allElements" select="$selectedElements"/>
1838                <xsl:call-template name="processElements">
1839                  <xsl:with-param name="eBare" select="$eBare"/>
1840                  <xsl:with-param name="kBare" select="$kBare"/>
1841                  <xsl:with-param name="vBare" select="$vBare"/>
1842                  <xsl:with-param name="layer" select="$layer"/>
1843                  <xsl:with-param name="elements" select="$allElements"/>
1844                  <xsl:with-param name="rule" select="$rule"/>
1845                </xsl:call-template>
1846              </xsl:when>
1847              <!-- every key , selected values -->
1848              <xsl:otherwise>
1849                <xsl:variable name="allElementsWithValue" select="$selectedElements[key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))]]"/>
1850                <xsl:call-template name="processElements">
1851                  <xsl:with-param name="eBare" select="$eBare"/>
1852                  <xsl:with-param name="kBare" select="$kBare"/>
1853                  <xsl:with-param name="vBare" select="$vBare"/>
1854                  <xsl:with-param name="layer" select="$layer"/>
1855                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
1856                  <xsl:with-param name="rule" select="$rule"/>
1857                </xsl:call-template>
1858              </xsl:otherwise>
1859            </xsl:choose>
1860          </xsl:when>
1861          <!-- no value  -->
1862          <xsl:when test="contains($v,'|~|')">
1863            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])=0]"/>
1864            <xsl:call-template name="processElements">
1865              <xsl:with-param name="eBare" select="$eBare"/>
1866              <xsl:with-param name="kBare" select="$kBare"/>
1867              <xsl:with-param name="vBare" select="$vBare"/>
1868              <xsl:with-param name="layer" select="$layer"/>
1869              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
1870              <xsl:with-param name="rule" select="$rule"/>
1871            </xsl:call-template>
1872          </xsl:when>
1873          <!-- every value  -->
1874          <xsl:when test="contains($v,'|*|')">
1875            <xsl:variable name="allElementsWithKey" select="$selectedElements[key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))]]"/>
1876            <xsl:call-template name="processElements">
1877              <xsl:with-param name="eBare" select="$eBare"/>
1878              <xsl:with-param name="kBare" select="$kBare"/>
1879              <xsl:with-param name="vBare" select="$vBare"/>
1880              <xsl:with-param name="layer" select="$layer"/>
1881              <xsl:with-param name="elements" select="$allElementsWithKey"/>
1882              <xsl:with-param name="rule" select="$rule"/>
1883            </xsl:call-template>
1884          </xsl:when>
1885
1886          <!-- defined key and defined value -->
1887          <xsl:otherwise>
1888            <xsl:variable name="elementsWithKey" select="$selectedElements[
1889                                                        key('wayByNode',@id)/tag[
1890                                                                contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
1891                                                                ]
1892                                                        ]"/>
1893            <xsl:call-template name="processElements">
1894              <xsl:with-param name="eBare" select="$eBare"/>
1895              <xsl:with-param name="kBare" select="$kBare"/>
1896              <xsl:with-param name="vBare" select="$vBare"/>
1897              <xsl:with-param name="layer" select="$layer"/>
1898              <xsl:with-param name="elements" select="$elementsWithKey"/>
1899              <xsl:with-param name="rule" select="$rule"/>
1900            </xsl:call-template>
1901          </xsl:otherwise>
1902        </xsl:choose>
1903      </xsl:when>
1904
1905      <!-- other selector -->
1906      <xsl:otherwise>
1907        <xsl:choose>
1908          <xsl:when test="contains($k,'|*|')">
1909            <xsl:choose>
1910              <xsl:when test="contains($v,'|~|')">
1911                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)=0]"/>
1912                <xsl:call-template name="processElements">
1913                  <xsl:with-param name="eBare" select="$eBare"/>
1914                  <xsl:with-param name="kBare" select="$kBare"/>
1915                  <xsl:with-param name="vBare" select="$vBare"/>
1916                  <xsl:with-param name="layer" select="$layer"/>
1917                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
1918                  <xsl:with-param name="rule" select="$rule"/>
1919                </xsl:call-template>
1920              </xsl:when>
1921              <xsl:when test="contains($v,'|*|')">
1922                <xsl:variable name="allElements" select="$selectedElements"/>
1923                <xsl:call-template name="processElements">
1924                  <xsl:with-param name="eBare" select="$eBare"/>
1925                  <xsl:with-param name="kBare" select="$kBare"/>
1926                  <xsl:with-param name="vBare" select="$vBare"/>
1927                  <xsl:with-param name="layer" select="$layer"/>
1928                  <xsl:with-param name="elements" select="$allElements"/>
1929                  <xsl:with-param name="rule" select="$rule"/>
1930                </xsl:call-template>
1931              </xsl:when>
1932              <xsl:otherwise>
1933                <xsl:variable name="allElementsWithValue" select="$selectedElements[tag[contains($v,concat('|',@v,'|'))]]"/>
1934                <xsl:call-template name="processElements">
1935                  <xsl:with-param name="eBare" select="$eBare"/>
1936                  <xsl:with-param name="kBare" select="$kBare"/>
1937                  <xsl:with-param name="vBare" select="$vBare"/>
1938                  <xsl:with-param name="layer" select="$layer"/>
1939                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
1940                  <xsl:with-param name="rule" select="$rule"/>
1941                </xsl:call-template>
1942              </xsl:otherwise>
1943            </xsl:choose>
1944          </xsl:when>
1945          <xsl:when test="contains($v,'|~|')">
1946            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])=0]"/>
1947            <xsl:call-template name="processElements">
1948              <xsl:with-param name="eBare" select="$eBare"/>
1949              <xsl:with-param name="kBare" select="$kBare"/>
1950              <xsl:with-param name="vBare" select="$vBare"/>
1951              <xsl:with-param name="layer" select="$layer"/>
1952              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
1953              <xsl:with-param name="rule" select="$rule"/>
1954            </xsl:call-template>
1955          </xsl:when>
1956          <xsl:when test="contains($v,'|*|')">
1957            <xsl:variable name="allElementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|'))]]"/>
1958            <xsl:call-template name="processElements">
1959              <xsl:with-param name="eBare" select="$eBare"/>
1960              <xsl:with-param name="kBare" select="$kBare"/>
1961              <xsl:with-param name="vBare" select="$vBare"/>
1962              <xsl:with-param name="layer" select="$layer"/>
1963              <xsl:with-param name="elements" select="$allElementsWithKey"/>
1964              <xsl:with-param name="rule" select="$rule"/>
1965            </xsl:call-template>
1966          </xsl:when>
1967          <xsl:otherwise>
1968            <xsl:variable name="elementsWithKey" select="$selectedElements[tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))]]"/>
1969            <xsl:call-template name="processElements">
1970              <xsl:with-param name="eBare" select="$eBare"/>
1971              <xsl:with-param name="kBare" select="$kBare"/>
1972              <xsl:with-param name="vBare" select="$vBare"/>
1973              <xsl:with-param name="layer" select="$layer"/>
1974              <xsl:with-param name="elements" select="$elementsWithKey"/>
1975              <xsl:with-param name="rule" select="$rule"/>
1976            </xsl:call-template>
1977          </xsl:otherwise>
1978        </xsl:choose>
1979      </xsl:otherwise>
1980    </xsl:choose>
1981  </xsl:template>
1982
1983
1984  <xsl:template match="else">
1985    <xsl:param name="elements"/>
1986    <xsl:param name="layer"/>
1987
1988    <!-- This is the previous rule that is being negated -->
1989    <!-- TODO: abort if no preceding rule element -->
1990    <xsl:variable name="rule" select="preceding-sibling::rule[1]"/>
1991
1992    <!-- Make list of elements that this rule should be applied to -->
1993    <xsl:variable name="eBare">
1994      <xsl:choose>
1995        <xsl:when test="$rule/@e='*'">node|way</xsl:when>
1996        <xsl:when test="$rule/@e">
1997          <xsl:value-of select="$rule/@e"/>
1998        </xsl:when>
1999        <xsl:otherwise>node|way</xsl:otherwise>
2000      </xsl:choose>
2001    </xsl:variable>
2002
2003    <!-- List of keys that this rule should be applied to -->
2004    <xsl:variable name="kBare" select="$rule/@k"/>
2005
2006    <!-- List of values that this rule should be applied to -->
2007    <xsl:variable name="vBare" select="$rule/@v"/>
2008    <xsl:variable name="sBare" select="$rule/@s"/>
2009
2010
2011    <!-- Top'n'tail selectors with | for contains usage -->
2012    <xsl:variable name="e">
2013      |<xsl:value-of select="$eBare"/>|
2014    </xsl:variable>
2015    <xsl:variable name="k">
2016      |<xsl:value-of select="$kBare"/>|
2017    </xsl:variable>
2018    <xsl:variable name="v">
2019      |<xsl:value-of select="$vBare"/>|
2020    </xsl:variable>
2021    <xsl:variable name="s">
2022      |<xsl:value-of select="$sBare"/>|
2023    </xsl:variable>
2024
2025    <xsl:variable
2026      name="selectedElements"
2027      select="$elements[contains($e,concat('|',name(),'|'))
2028              or
2029              (contains($e,'|node|') and name()='way'and key('wayByNode',@id))
2030              ]"/>
2031
2032    <!-- Patch $s -->
2033    <xsl:choose>
2034      <xsl:when test="contains($s,'|way|')">
2035        <xsl:choose>
2036          <xsl:when test="contains($k,'|*|')">
2037            <xsl:choose>
2038              <xsl:when test="contains($v,'|~|')">
2039                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(key('wayByNode',@id)/tag)!=0]"/>
2040                <xsl:call-template name="processElements">
2041                  <xsl:with-param name="eBare" select="$eBare"/>
2042                  <xsl:with-param name="kBare" select="$kBare"/>
2043                  <xsl:with-param name="vBare" select="$vBare"/>
2044                  <xsl:with-param name="layer" select="$layer"/>
2045                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2046                  <xsl:with-param name="rule" select="$rule"/>
2047                </xsl:call-template>
2048              </xsl:when>
2049              <xsl:when test="contains($v,'|*|')">
2050                <!-- no-op! -->
2051              </xsl:when>
2052              <xsl:otherwise>
2053                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(key('wayByNode',@id)/tag[contains($v,concat('|',@v,'|'))])]"/>
2054                <xsl:call-template name="processElements">
2055                  <xsl:with-param name="eBare" select="$eBare"/>
2056                  <xsl:with-param name="kBare" select="$kBare"/>
2057                  <xsl:with-param name="vBare" select="$vBare"/>
2058                  <xsl:with-param name="layer" select="$layer"/>
2059                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2060                  <xsl:with-param name="rule" select="$rule"/>
2061                </xsl:call-template>
2062              </xsl:otherwise>
2063            </xsl:choose>
2064          </xsl:when>
2065          <xsl:when test="contains($v,'|~|')">
2066            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2067            <xsl:call-template name="processElements">
2068              <xsl:with-param name="eBare" select="$eBare"/>
2069              <xsl:with-param name="kBare" select="$kBare"/>
2070              <xsl:with-param name="vBare" select="$vBare"/>
2071              <xsl:with-param name="layer" select="$layer"/>
2072              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2073              <xsl:with-param name="rule" select="$rule"/>
2074            </xsl:call-template>
2075          </xsl:when>
2076          <xsl:when test="contains($v,'|*|')">
2077            <xsl:variable name="allElementsWithKey" select="$selectedElements[not(key('wayByNode',@id)/tag[contains($k,concat('|',@k,'|'))])]"/>
2078            <xsl:call-template name="processElements">
2079              <xsl:with-param name="eBare" select="$eBare"/>
2080              <xsl:with-param name="kBare" select="$kBare"/>
2081              <xsl:with-param name="vBare" select="$vBare"/>
2082              <xsl:with-param name="layer" select="$layer"/>
2083              <xsl:with-param name="elements" select="$allElementsWithKey"/>
2084              <xsl:with-param name="rule" select="$rule"/>
2085            </xsl:call-template>
2086          </xsl:when>
2087          <xsl:otherwise>
2088            <xsl:variable name="elementsWithKey" select="$selectedElements[not(
2089                         key('wayByNode',@id)/tag[
2090                            contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))
2091                            ]
2092                         )]"/>
2093            <xsl:call-template name="processElements">
2094              <xsl:with-param name="eBare" select="$eBare"/>
2095              <xsl:with-param name="kBare" select="$kBare"/>
2096              <xsl:with-param name="vBare" select="$vBare"/>
2097              <xsl:with-param name="layer" select="$layer"/>
2098              <xsl:with-param name="elements" select="$elementsWithKey"/>
2099              <xsl:with-param name="rule" select="$rule"/>
2100            </xsl:call-template>
2101          </xsl:otherwise>
2102        </xsl:choose>
2103      </xsl:when>
2104
2105      <xsl:otherwise>
2106        <!-- not contains $s -->
2107        <xsl:choose>
2108          <xsl:when test="contains($k,'|*|')">
2109            <xsl:choose>
2110              <xsl:when test="contains($v,'|~|')">
2111                <xsl:variable name="elementsWithNoTags" select="$selectedElements[count(tag)!=0]"/>
2112                <xsl:call-template name="processElements">
2113                  <xsl:with-param name="eBare" select="$eBare"/>
2114                  <xsl:with-param name="kBare" select="$kBare"/>
2115                  <xsl:with-param name="vBare" select="$vBare"/>
2116                  <xsl:with-param name="layer" select="$layer"/>
2117                  <xsl:with-param name="elements" select="$elementsWithNoTags"/>
2118                  <xsl:with-param name="rule" select="$rule"/>
2119                </xsl:call-template>
2120              </xsl:when>
2121              <xsl:when test="contains($v,'|*|')">
2122                <!-- no-op! -->
2123              </xsl:when>
2124              <xsl:otherwise>
2125                <xsl:variable name="allElementsWithValue" select="$selectedElements[not(tag[contains($v,concat('|',@v,'|'))])]"/>
2126                <xsl:call-template name="processElements">
2127                  <xsl:with-param name="eBare" select="$eBare"/>
2128                  <xsl:with-param name="kBare" select="$kBare"/>
2129                  <xsl:with-param name="vBare" select="$vBare"/>
2130                  <xsl:with-param name="layer" select="$layer"/>
2131                  <xsl:with-param name="elements" select="$allElementsWithValue"/>
2132                  <xsl:with-param name="rule" select="$rule"/>
2133                </xsl:call-template>
2134              </xsl:otherwise>
2135            </xsl:choose>
2136          </xsl:when>
2137          <xsl:when test="contains($v,'|~|')">
2138            <xsl:variable name="elementsWithoutKey" select="$selectedElements[count(tag[contains($k,concat('|',@k,'|'))])!=0]"/>
2139            <xsl:call-template name="processElements">
2140              <xsl:with-param name="eBare" select="$eBare"/>
2141              <xsl:with-param name="kBare" select="$kBare"/>
2142              <xsl:with-param name="vBare" select="$vBare"/>
2143              <xsl:with-param name="layer" select="$layer"/>
2144              <xsl:with-param name="elements" select="$elementsWithoutKey"/>
2145              <xsl:with-param name="rule" select="$rule"/>
2146            </xsl:call-template>
2147          </xsl:when>
2148          <xsl:when test="contains($v,'|*|')">
2149            <xsl:variable name="allElementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|'))])]"/>
2150            <xsl:call-template name="processElements">
2151              <xsl:with-param name="eBare" select="$eBare"/>
2152              <xsl:with-param name="kBare" select="$kBare"/>
2153              <xsl:with-param name="vBare" select="$vBare"/>
2154              <xsl:with-param name="layer" select="$layer"/>
2155              <xsl:with-param name="elements" select="$allElementsWithKey"/>
2156              <xsl:with-param name="rule" select="$rule"/>
2157            </xsl:call-template>
2158          </xsl:when>
2159          <xsl:otherwise>
2160            <xsl:variable name="elementsWithKey" select="$selectedElements[not(tag[contains($k,concat('|',@k,'|')) and contains($v,concat('|',@v,'|'))])]"/>
2161            <xsl:call-template name="processElements">
2162              <xsl:with-param name="eBare" select="$eBare"/>
2163              <xsl:with-param name="kBare" select="$kBare"/>
2164              <xsl:with-param name="vBare" select="$vBare"/>
2165              <xsl:with-param name="layer" select="$layer"/>
2166              <xsl:with-param name="elements" select="$elementsWithKey"/>
2167              <xsl:with-param name="rule" select="$rule"/>
2168            </xsl:call-template>
2169          </xsl:otherwise>
2170        </xsl:choose>
2171      </xsl:otherwise>
2172    </xsl:choose>
2173  </xsl:template>
2174
2175
2176  <xsl:template name="processElements">
2177    <xsl:param name="eBare"/>
2178    <xsl:param name="kBare"/>
2179    <xsl:param name="vBare"/>
2180    <xsl:param name="layer"/>
2181    <xsl:param name="elements"/>
2182    <xsl:param name="rule"/>
2183
2184    <xsl:if test="$elements">
2185      <xsl:message>
2186        Processing &lt;rule e="<xsl:value-of select="$eBare"/>" k="<xsl:value-of select="$kBare"/>" v="<xsl:value-of select="$vBare"/>" &gt;
2187        Matched by <xsl:value-of select="count($elements)"/> elements for layer <xsl:value-of select="$layer"/>.
2188      </xsl:message>
2189
2190      <xsl:apply-templates select="*">
2191        <xsl:with-param name="layer" select="$layer"/>
2192        <xsl:with-param name="elements" select="$elements"/>
2193        <xsl:with-param name="rule" select="$rule"/>
2194      </xsl:apply-templates>
2195    </xsl:if>
2196  </xsl:template>
2197
2198  <!-- Draw SVG layers -->
2199  <xsl:template match="layer">
2200    <xsl:param name="elements"/>
2201    <xsl:param name="layer"/>
2202    <xsl:param name="rule"/>
2203
2204    <xsl:message>
2205      Processing SVG layer: <xsl:value-of select="@name"/> (at OSM layer <xsl:value-of select="$layer"/>)
2206    </xsl:message>
2207
2208    <xsl:variable name="opacity">
2209      <xsl:if test="@opacity">
2210        <xsl:value-of select="concat('opacity:',@opacity,';')"/>
2211      </xsl:if>
2212    </xsl:variable>
2213
2214    <xsl:variable name="display">
2215      <xsl:if test="(@display='none') or (@display='off')">
2216        <xsl:text>display:none;</xsl:text>
2217      </xsl:if>
2218    </xsl:variable>
2219
2220    <g inkscape:groupmode="layer" id="{@name}-{$layer}" inkscape:label="{@name}">
2221      <xsl:if test="concat($opacity,$display)!=''">
2222        <xsl:attribute name="style">
2223          <xsl:value-of select="concat($opacity,$display)"/>
2224        </xsl:attribute>
2225      </xsl:if>
2226      <xsl:apply-templates select="*">
2227        <xsl:with-param name="layer" select="$layer"/>
2228        <xsl:with-param name="elements" select="$elements"/>
2229      </xsl:apply-templates>
2230    </g>
2231
2232  </xsl:template>
2233
2234
2235  <!-- Draw map border -->
2236  <xsl:template name="drawBorder">
2237    <!-- dasharray definitions here can be overridden in stylesheet -->
2238    <g id="border" inkscape:groupmode="layer" inkscape:label="Map Border">
2239      <line id="border-left-casing" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2240      <line id="border-top-casing" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2241      <line id="border-bottom-casing" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2242      <line id="border-right-casing" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-casing" stroke-dasharray="{($km div 10) - 1},1"/>
2243
2244      <line id="border-left-core" x1="0" y1="0" x2="0" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2245      <line id="border-top-core" x1="0" y1="0" x2="{$documentWidth}" y2="0" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2246      <line id="border-bottom-core" x1="0" y1="{$documentHeight}" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2247      <line id="border-right-core" x1="{$documentWidth}" y1="0" x2="{$documentWidth}" y2="{$documentHeight}" class="map-border-core" stroke-dasharray="{($km div 10) - 1},1"/>
2248    </g>
2249  </xsl:template>
2250
2251
2252  <!-- Draw a grid over the map in 1km increments -->
2253  <xsl:template name="drawGrid">
2254    <g id="grid" inkscape:groupmode="layer" inkscape:label="Grid">
2255      <xsl:call-template name="drawGridHorizontals">
2256        <xsl:with-param name="line" select="'1'"/>
2257      </xsl:call-template>
2258      <xsl:call-template name="drawGridVerticals">
2259        <xsl:with-param name="line" select="'1'"/>
2260      </xsl:call-template>
2261    </g>
2262  </xsl:template>
2263
2264
2265  <xsl:template name="drawGridHorizontals">
2266    <xsl:param name="line"/>
2267    <xsl:if test="($line*$km) &lt; $documentHeight">
2268      <line id="grid-hori-{$line}" x1="0px" y1="{$line*$km}px" x2="{$documentWidth}px" y2="{$line*$km}px" class="map-grid-line"/>
2269      <xsl:call-template name="drawGridHorizontals">
2270        <xsl:with-param name="line" select="$line+1"/>
2271      </xsl:call-template>
2272    </xsl:if>
2273  </xsl:template>
2274
2275
2276  <xsl:template name="drawGridVerticals">
2277    <xsl:param name="line"/>
2278    <xsl:if test="($line*$km) &lt; $documentWidth">
2279      <line id="grid-vert-{$line}" x1="{$line*$km}px" y1="0px" x2="{$line*$km}px" y2="{$documentHeight}px" class="map-grid-line"/>
2280      <xsl:call-template name="drawGridVerticals">
2281        <xsl:with-param name="line" select="$line+1"/>
2282      </xsl:call-template>
2283    </xsl:if>
2284  </xsl:template>
2285
2286
2287  <!-- Draw map title -->
2288  <xsl:template name="drawTitle">
2289    <xsl:param name="title"/>
2290
2291    <xsl:variable name="x" select="$documentWidth div 2"/>
2292    <xsl:variable name="y" select="30"/>
2293
2294    <g id="marginalia-title" inkscape:groupmode="layer" inkscape:label="Title">
2295      <rect id="marginalia-title-background" x="0px" y="0px" height="{$marginaliaTopHeight - 5}px" width="{$documentWidth}px" class="map-title-background"/>
2296      <text id="marginalia-title-text" class="map-title" x="{$x}" y="{$y}">
2297        <xsl:value-of select="$title"/>
2298      </text>
2299    </g>
2300  </xsl:template>
2301
2302
2303  <!-- Draw an approximate scale in the bottom left corner of the map -->
2304  <xsl:template name="drawScale">
2305    <xsl:variable name="x1" select="14"/>
2306    <xsl:variable name="y1" select="round(($documentHeight)+((($bottomLeftLatitude)-(number($bottomLeftLatitude)))*10000*$scale*$projection))+28"/>
2307    <xsl:variable name="x2" select="$x1+$km"/>
2308    <xsl:variable name="y2" select="$y1"/>
2309
2310    <g id="marginalia-scale" inkscape:groupmode="layer" inkscape:label="Scale">
2311      <line id="marginalia-scale-casing" class="map-scale-casing" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
2312
2313      <line id="marginalia-scale-core" class="map-scale-core" stroke-dasharray="{($km div 10)}" x1="{$x1}" y1="{$y1}" x2="{$x2}" y2="{$y2}"/>
2314
2315      <line id="marginalia-scale-bookend-from" class="map-scale-bookend" x1="{$x1}" y1="{$y1 + 2}" x2="{$x1}" y2="{$y1 - 10}"/>
2316
2317      <line id="marginalia-scale-bookend-to" class="map-scale-bookend" x1="{$x2}" y1="{$y2 + 2}" x2="{$x2}" y2="{$y2 - 10}"/>
2318
2319      <text id="marginalia-scale-text-from" class="map-scale-caption" x="{$x1}" y="{$y1 - 10}">0</text>
2320
2321      <text id="marginalia-scale-text-to" class="map-scale-caption" x="{$x2}" y="{$y2 - 10}">1km</text>
2322    </g>
2323  </xsl:template>
2324
2325
2326  <!-- Create a comment in SVG source code and RDF description of license -->
2327  <xsl:template name="metadata">
2328
2329    <xsl:comment>
2330
2331      Copyright (c) <xsl:value-of select="$year"/> OpenStreetMap
2332      www.openstreetmap.org
2333      This work is licensed under the
2334      Creative Commons Attribution-ShareAlike 2.0 License.
2335      http://creativecommons.org/licenses/by-sa/2.0/
2336
2337    </xsl:comment>
2338    <metadata id="metadata">
2339      <rdf:RDF xmlns="http://web.resource.org/cc/">
2340        <cc:Work rdf:about="">
2341          <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
2342          <dc:format>image/svg+xml</dc:format>
2343          <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
2344          <dc:title>
2345            <xsl:value-of select="$title"/>
2346          </dc:title>
2347          <dc:date>
2348            <xsl:value-of select="$date"/>
2349          </dc:date>
2350          <dc:source>http://www.openstreetmap.org/</dc:source>
2351        </cc:Work>
2352        <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
2353          <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
2354          <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
2355          <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
2356          <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
2357          <cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
2358          <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
2359        </cc:License>
2360      </rdf:RDF>
2361    </metadata>
2362  </xsl:template>
2363
2364  <!-- Create a license logo and description in the image -->
2365  <xsl:template name="in-image-license">
2366    <xsl:param name="dx"/>
2367    <xsl:param name="dy"/>
2368
2369    <g id="license" inkscape:groupmode="layer" inkscape:label="Copyright" transform="translate({$dx},{$dy})">
2370      <style type="text/css">
2371        <![CDATA[
2372                .license-text {
2373                    text-anchor: left;
2374                    font-family: "DejaVu Sans",sans-serif;
2375                    font-size: 6px;
2376                    fill: black;
2377                }
2378            ]]>
2379      </style>
2380      <a id="license-cc-logo-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
2381        <g id="license-cc-logo" transform="scale(0.5,0.5) translate(-604,-49)">
2382          <path id="path3817_2_" nodetypes="ccccccc" d="M
2383                    182.23532,75.39014 L 296.29928,75.59326 C
2384                    297.89303,75.59326 299.31686,75.35644 299.31686,78.77344 L
2385                    299.17721,116.34033 L 179.3569,116.34033 L
2386                    179.3569,78.63379 C 179.3569,76.94922 179.51999,75.39014
2387                    182.23532,75.39014 z " style="fill:#aab2ab"/>
2388          <g id="g5908_2_" transform="matrix(0.872921,0,0,0.872921,50.12536,143.2144)">
2389            <path id="path5906_2_" type="arc" cx="296.35416"
2390            cy="264.3577" ry="22.939548" rx="22.939548" d="M
2391                        187.20944,-55.6792 C 187.21502,-46.99896
2392                        180.18158,-39.95825 171.50134,-39.95212 C
2393                        162.82113,-39.94708 155.77929,-46.97998
2394                        155.77426,-55.66016 C 155.77426,-55.66687
2395                        155.77426,-55.67249 155.77426,-55.6792 C
2396                        155.76922,-64.36054 162.80209,-71.40125
2397                        171.48233,-71.40631 C 180.16367,-71.41193
2398                        187.20441,-64.37842 187.20944,-55.69824 C
2399                        187.20944,-55.69263 187.20944,-55.68591
2400                        187.20944,-55.6792 z " style="fill:white"/>
2401            <g id="g5706_2_" transform="translate(-289.6157,99.0653)">
2402              <path id="path5708_2_" d="M 473.88455,-167.54724 C
2403                            477.36996,-164.06128 479.11294,-159.79333
2404                            479.11294,-154.74451 C 479.11294,-149.69513
2405                            477.40014,-145.47303 473.9746,-142.07715 C
2406                            470.33929,-138.50055 466.04281,-136.71283
2407                            461.08513,-136.71283 C 456.18736,-136.71283
2408                            451.96526,-138.48544 448.42003,-142.03238 C
2409                            444.87419,-145.57819 443.10158,-149.81537
2410                            443.10158,-154.74451 C 443.10158,-159.6731
2411                            444.87419,-163.94049 448.42003,-167.54724 C
2412                            451.87523,-171.03375 456.09728,-172.77618
2413                            461.08513,-172.77618 C 466.13342,-172.77618
2414                            470.39914,-171.03375 473.88455,-167.54724 z M
2415                            450.76657,-165.20239 C 447.81982,-162.22601
2416                            446.34701,-158.7395 446.34701,-154.74005 C
2417                            446.34701,-150.7417 447.80529,-147.28485
2418                            450.72125,-144.36938 C 453.63778,-141.45288
2419                            457.10974,-139.99462 461.1383,-139.99462 C
2420                            465.16683,-139.99462 468.66848,-141.46743
2421                            471.64486,-144.41363 C 474.47076,-147.14947
2422                            475.88427,-150.59069 475.88427,-154.74005 C
2423                            475.88427,-158.85809 474.44781,-162.35297
2424                            471.57659,-165.22479 C 468.70595,-168.09546
2425                            465.22671,-169.53131 461.1383,-169.53131 C
2426                            457.04993,-169.53131 453.59192,-168.08813
2427                            450.76657,-165.20239 z M 458.52106,-156.49927 C
2428                            458.07074,-157.4809 457.39673,-157.9715
2429                            456.49781,-157.9715 C 454.90867,-157.9715
2430                            454.11439,-156.90198 454.11439,-154.763 C
2431                            454.11439,-152.62341 454.90867,-151.55389
2432                            456.49781,-151.55389 C 457.54719,-151.55389
2433                            458.29676,-152.07519 458.74647,-153.11901 L
2434                            460.94923,-151.94598 C 459.8993,-150.0805
2435                            458.32417,-149.14697 456.22374,-149.14697 C
2436                            454.60384,-149.14697 453.30611,-149.64367
2437                            452.33168,-150.63653 C 451.35561,-151.62994
2438                            450.86894,-152.99926 450.86894,-154.7445 C
2439                            450.86894,-156.46008 451.37123,-157.82159
2440                            452.37642,-158.83013 C 453.38161,-159.83806
2441                            454.63347,-160.34264 456.13423,-160.34264 C
2442                            458.35435,-160.34264 459.94407,-159.46776
2443                            460.90504,-157.71978 L 458.52106,-156.49927 z M
2444                            468.8844,-156.49927 C 468.43353,-157.4809
2445                            467.77292,-157.9715 466.90201,-157.9715 C
2446                            465.28095,-157.9715 464.46988,-156.90198
2447                            464.46988,-154.763 C 464.46988,-152.62341
2448                            465.28095,-151.55389 466.90201,-151.55389 C
2449                            467.95304,-151.55389 468.68918,-152.07519
2450                            469.10925,-153.11901 L 471.36126,-151.94598 C
2451                            470.31301,-150.0805 468.74007,-149.14697
2452                            466.64358,-149.14697 C 465.02587,-149.14697
2453                            463.73095,-149.64367 462.75711,-150.63653 C
2454                            461.78494,-151.62994 461.29773,-152.99926
2455                            461.29773,-154.7445 C 461.29773,-156.46008
2456                            461.79221,-157.82159 462.78061,-158.83013 C
2457                            463.76843,-159.83806 465.02588,-160.34264
2458                            466.55408,-160.34264 C 468.77027,-160.34264
2459                            470.35776,-159.46776 471.3154,-157.71978 L
2460                            468.8844,-156.49927 z "/>
2461            </g>
2462          </g>
2463          <path d="M 297.29639,74.91064 L 181.06688,74.91064 C
2464                    179.8203,74.91064 178.80614,75.92529 178.80614,77.17187 L
2465                    178.80614,116.66748 C 178.80614,116.94922
2466                    179.03466,117.17822 179.31639,117.17822 L
2467                    299.04639,117.17822 C 299.32813,117.17822
2468                    299.55713,116.94922 299.55713,116.66748 L
2469                    299.55713,77.17188 C 299.55713,75.92529 298.54297,74.91064
2470                    297.29639,74.91064 z M 181.06688,75.93213 L
2471                    297.29639,75.93213 C 297.97998,75.93213 298.53565,76.48828
2472                    298.53565,77.17188 C 298.53565,77.17188 298.53565,93.09131
2473                    298.53565,104.59034 L 215.4619,104.59034 C
2474                    212.41698,110.09571 206.55077,113.83399 199.81835,113.83399
2475                    C 193.083,113.83399 187.21825,110.09913 184.1748,104.59034
2476                    L 179.82666,104.59034 C 179.82666,93.09132
2477                    179.82666,77.17188 179.82666,77.17188 C 179.82664,76.48828
2478                    180.38329,75.93213 181.06688,75.93213 z " id="frame"/>
2479          <g enable-background="new" id="g2821">
2480            <path d="M 265.60986,112.8833 C 265.68994,113.03906
2481                        265.79736,113.16504 265.93115,113.26172 C
2482                        266.06494,113.35791 266.22119,113.42969
2483                        266.40088,113.47608 C 266.58154,113.52296
2484                        266.76807,113.54639 266.96045,113.54639 C
2485                        267.09033,113.54639 267.22998,113.53565
2486                        267.3794,113.51368 C 267.52784,113.4922
2487                        267.66749,113.44972 267.79835,113.3877 C
2488                        267.92823,113.32569 268.03761,113.23975
2489                        268.12355,113.13086 C 268.21144,113.02197
2490                        268.25441,112.88379 268.25441,112.71533 C
2491                        268.25441,112.53515 268.19679,112.38916
2492                        268.08156,112.27685 C 267.9673,112.16455
2493                        267.81594,112.07177 267.62941,111.99658 C
2494                        267.44386,111.92236 267.23195,111.85693
2495                        266.9966,111.80078 C 266.76027,111.74463
2496                        266.52101,111.68262 266.27883,111.61377 C
2497                        266.02981,111.55176 265.78762,111.47559
2498                        265.55129,111.38525 C 265.31594,111.29541
2499                        265.10402,111.17822 264.9175,111.03515 C
2500                        264.73098,110.89208 264.58059,110.71337
2501                        264.46535,110.49853 C 264.35109,110.28369
2502                        264.29347,110.02392 264.29347,109.71923 C
2503                        264.29347,109.37646 264.36671,109.07958
2504                        264.51222,108.82763 C 264.6587,108.57568
2505                        264.85011,108.36572 265.08644,108.19726 C
2506                        265.32179,108.02929 265.58937,107.90478
2507                        265.8882,107.82372 C 266.18605,107.74315
2508                        266.48488,107.70263 266.78273,107.70263 C
2509                        267.13136,107.70263 267.46535,107.74169
2510                        267.78566,107.81982 C 268.105,107.89746
2511                        268.39015,108.02392 268.6382,108.19824 C
2512                        268.88722,108.37256 269.08449,108.59521
2513                        269.23097,108.86621 C 269.37648,109.13721
2514                        269.44972,109.46582 269.44972,109.85156 L
2515                        268.02784,109.85156 C 268.01514,109.65234
2516                        267.97315,109.4873 267.90284,109.35693 C
2517                        267.83155,109.22607 267.73682,109.12353
2518                        267.61964,109.04834 C 267.50148,108.97412
2519                        267.36671,108.9209 267.21534,108.89014 C
2520                        267.063,108.85889 266.89796,108.84326
2521                        266.71827,108.84326 C 266.60108,108.84326
2522                        266.48292,108.85596 266.36573,108.88037 C
2523                        266.24757,108.90576 266.14112,108.94922
2524                        266.04542,109.01123 C 265.94874,109.07373
2525                        265.86964,109.15137 265.80812,109.24463 C
2526                        265.7466,109.33838 265.71535,109.45654
2527                        265.71535,109.59961 C 265.71535,109.73047
2528                        265.73976,109.83643 265.78957,109.91699 C
2529                        265.83937,109.99804 265.93801,110.07275
2530                        266.08352,110.14111 C 266.22903,110.20947
2531                        266.43118,110.27832 266.68899,110.34668 C
2532                        266.9468,110.41504 267.28372,110.50244
2533                        267.70071,110.60791 C 267.82473,110.63281
2534                        267.99661,110.67822 268.21731,110.74365 C
2535                        268.43801,110.80908 268.65676,110.91308
2536                        268.87454,111.05615 C 269.09231,111.1997
2537                        269.27981,111.39111 269.43899,111.63037 C
2538                        269.59719,111.87012 269.67629,112.17676
2539                        269.67629,112.55029 C 269.67629,112.85547
2540                        269.61672,113.13867 269.49856,113.3999 C
2541                        269.3804,113.66162 269.20461,113.8872
2542                        268.97122,114.07666 C 268.73782,114.26709
2543                        268.44876,114.41455 268.10403,114.52051 C
2544                        267.75833,114.62647 267.35794,114.6792
2545                        266.90481,114.6792 C 266.53762,114.6792
2546                        266.18118,114.63379 265.83547,114.54346 C
2547                        265.49074,114.45313 265.18508,114.31104
2548                        264.92043,114.11768 C 264.65676,113.92432
2549                        264.4468,113.67774 264.29055,113.37891 C
2550                        264.13528,113.07959 264.06106,112.7251
2551                        264.06692,112.31397 L 265.4888,112.31397 C
2552                        265.48877,112.53809 265.52881,112.72803
2553                        265.60986,112.8833 z " id="path2823"
2554            style="fill:white"/>
2555            <path d="M 273.8667,107.8667 L
2556                        276.35986,114.53076 L 274.8374,114.53076 L
2557                        274.33349,113.04638 L 271.84033,113.04638 L
2558                        271.31787,114.53076 L 269.84326,114.53076 L
2559                        272.36377,107.8667 L 273.8667,107.8667 z M
2560                        273.95068,111.95264 L 273.11084,109.50928 L
2561                        273.09229,109.50928 L 272.22315,111.95264 L
2562                        273.95068,111.95264 z " id="path2825"
2563            style="fill:white"/>
2564          </g>
2565          <g enable-background="new" id="g2827">
2566            <path d="M 239.17821,107.8667 C 239.49559,107.8667
2567                        239.78563,107.89502 240.04735,107.95068 C
2568                        240.30907,108.00683 240.53368,108.09863
2569                        240.72118,108.22607 C 240.9077,108.35351
2570                        241.05321,108.52295 241.15575,108.73437 C
2571                        241.25829,108.94579 241.31005,109.20703
2572                        241.31005,109.51806 C 241.31005,109.854
2573                        241.23388,110.13329 241.08056,110.35742 C
2574                        240.92822,110.58154 240.70165,110.76465
2575                        240.40283,110.90771 C 240.81494,111.02587
2576                        241.12256,111.23291 241.32568,111.5288 C
2577                        241.5288,111.82469 241.63037,112.18114
2578                        241.63037,112.59814 C 241.63037,112.93408
2579                        241.56494,113.22509 241.43408,113.47119 C
2580                        241.30322,113.7168 241.12646,113.91748
2581                        240.90576,114.07324 C 240.68408,114.229
2582                        240.43115,114.34424 240.14795,114.41845 C
2583                        239.86377,114.49365 239.57275,114.53075
2584                        239.27295,114.53075 L 236.03662,114.53075 L
2585                        236.03662,107.86669 L 239.17821,107.86669 L
2586                        239.17821,107.8667 z M 238.99071,110.56201 C
2587                        239.25243,110.56201 239.46727,110.5 239.63622,110.37597
2588                        C 239.80419,110.25146 239.88817,110.05029
2589                        239.88817,109.77099 C 239.88817,109.61572
2590                        239.85985,109.48828 239.80419,109.38915 C
2591                        239.74755,109.28954 239.67333,109.21239
2592                        239.57958,109.15624 C 239.48583,109.10058
2593                        239.37841,109.06151 239.25731,109.04003 C
2594                        239.13524,109.01806 239.00926,109.00732
2595                        238.8784,109.00732 L 237.50535,109.00732 L
2596                        237.50535,110.56201 L 238.99071,110.56201 z M
2597                        239.07664,113.39014 C 239.22019,113.39014
2598                        239.35691,113.37647 239.48777,113.34815 C
2599                        239.61863,113.32032 239.73484,113.27344
2600                        239.83445,113.2085 C 239.93406,113.14307
2601                        240.01316,113.0542 240.07273,112.94239 C
2602                        240.1323,112.83058 240.1616,112.68751
2603                        240.1616,112.51319 C 240.1616,112.17139
2604                        240.06492,111.92725 239.87156,111.78126 C
2605                        239.6782,111.63527 239.42234,111.56202
2606                        239.10496,111.56202 L 237.50535,111.56202 L
2607                        237.50535,113.39014 L 239.07664,113.39014 z "
2608            id="path2829" style="fill:white"/>
2609            <path d="M 241.88914,107.8667 L 243.53269,107.8667 L
2610                        245.09324,110.49854 L 246.64402,107.8667 L
2611                        248.27781,107.8667 L 245.80418,111.97315 L
2612                        245.80418,114.53077 L 244.33543,114.53077 L
2613                        244.33543,111.93604 L 241.88914,107.8667 z "
2614            id="path2831" style="fill:white"/>
2615          </g>
2616          <g id="g6316_1_" transform="matrix(0.624995,0,0,0.624995,391.2294,176.9332)">
2617            <path id="path6318_1_" type="arc" cx="475.97119"
2618            cy="252.08646" ry="29.209877" rx="29.209877" d="M
2619                        -175.0083,-139.1153 C -175.00204,-129.7035
2620                        -182.62555,-122.06751 -192.03812,-122.06049 C
2621                        -201.44913,-122.05341 -209.08512,-129.67774
2622                        -209.09293,-139.09028 C -209.09293,-139.09809
2623                        -209.09293,-139.10749 -209.09293,-139.1153 C
2624                        -209.09919,-148.52784 -201.47413,-156.1623
2625                        -192.06311,-156.17011 C -182.65054,-156.17713
2626                        -175.01456,-148.55207 -175.0083,-139.14026 C
2627                        -175.0083,-139.13092 -175.0083,-139.1239
2628                        -175.0083,-139.1153 z " style="fill:white"/>
2629            <g id="g6320_1_" transform="translate(-23.9521,-89.72962)">
2630              <path id="path6322_1_" d="M -168.2204,-68.05536 C
2631                            -173.39234,-68.05536 -177.76892,-66.25067
2632                            -181.35175,-62.64203 C -185.02836,-58.90759
2633                            -186.86588,-54.48883 -186.86588,-49.38568 C
2634                            -186.86588,-44.28253 -185.02836,-39.89416
2635                            -181.35175,-36.22308 C -177.67673,-32.55114
2636                            -173.29859,-30.71521 -168.2204,-30.71521 C
2637                            -163.07974,-30.71521 -158.62503,-32.56677
2638                            -154.85312,-36.26996 C -151.30307,-39.78558
2639                            -149.52652,-44.15827 -149.52652,-49.38568 C
2640                            -149.52652,-54.6123 -151.33432,-59.03265
2641                            -154.94843,-62.64203 C -158.5625,-66.25067
2642                            -162.98599,-68.05536 -168.2204,-68.05536 z M
2643                            -168.17352,-64.69519 C -163.936,-64.69519
2644                            -160.33752,-63.20221 -157.37655,-60.21466 C
2645                            -154.38748,-57.25836 -152.89214,-53.64899
2646                            -152.89214,-49.38568 C -152.89214,-45.09186
2647                            -154.35466,-41.52856 -157.28438,-38.69653 C
2648                            -160.36876,-35.64727 -163.99849,-34.12304
2649                            -168.17351,-34.12304 C -172.34856,-34.12304
2650                            -175.94701,-35.63244 -178.96892,-38.64965 C
2651                            -181.9908,-41.66918 -183.50176,-45.24657
2652                            -183.50176,-49.38567 C -183.50176,-53.52398
2653                            -181.97518,-57.13414 -178.92205,-60.21465 C
2654                            -175.9939,-63.20221 -172.41107,-64.69519
2655                            -168.17352,-64.69519 z "/>
2656              <path id="path6324_1_" d="M -176.49548,-52.02087 C
2657                            -175.75171,-56.71856 -172.44387,-59.22949
2658                            -168.30008,-59.22949 C -162.33911,-59.22949
2659                            -158.70783,-54.90448 -158.70783,-49.1372 C
2660                            -158.70783,-43.50982 -162.57194,-39.13793
2661                            -168.39383,-39.13793 C -172.39856,-39.13793
2662                            -175.98297,-41.60277 -176.63611,-46.43877 L
2663                            -171.93292,-46.43877 C -171.7923,-43.92778
2664                            -170.1626,-43.04418 -167.83447,-43.04418 C
2665                            -165.1813,-43.04418 -163.4563,-45.50908
2666                            -163.4563,-49.27709 C -163.4563,-53.22942
2667                            -164.94693,-55.32244 -167.74228,-55.32244 C
2668                            -169.79074,-55.32244 -171.55948,-54.57787
2669                            -171.93292,-52.02087 L -170.56418,-52.02789 L
2670                            -174.26734,-48.32629 L -177.96894,-52.02789 L
2671                            -176.49548,-52.02087 z "/>
2672            </g>
2673          </g>
2674          <g id="g2838">
2675            <circle cx="242.56226" cy="90.224609" r="10.8064" id="circle2840" style="fill:white"/>
2676            <g id="g2842">
2677              <path d="M 245.68994,87.09766 C 245.68994,86.68116
2678                            245.35205,86.34424 244.93603,86.34424 L
2679                            240.16357,86.34424 C 239.74755,86.34424
2680                            239.40966,86.68115 239.40966,87.09766 L
2681                            239.40966,91.87061 L 240.74071,91.87061 L
2682                            240.74071,97.52295 L 244.3579,97.52295 L
2683                            244.3579,91.87061 L 245.68993,91.87061 L
2684                            245.68993,87.09766 L 245.68994,87.09766 z "
2685              id="path2844"/>
2686              <circle cx="242.5498" cy="84.083008" r="1.63232" id="circle2846"/>
2687            </g>
2688            <path clip-rule="evenodd" d="M 242.53467,78.31836 C
2689                        239.30322,78.31836 236.56641,79.4458 234.32715,81.70215
2690                        C 232.0293,84.03516 230.88086,86.79736
2691                        230.88086,89.98633 C 230.88086,93.1753
2692                        232.0293,95.91846 234.32715,98.21338 C
2693                        236.625,100.50781 239.36133,101.65527
2694                        242.53467,101.65527 C 245.74756,101.65527
2695                        248.53272,100.49853 250.88819,98.18359 C
2696                        253.10889,95.98681 254.21827,93.2539 254.21827,89.98632
2697                        C 254.21827,86.71874 253.08936,83.95751
2698                        250.83057,81.70214 C 248.57178,79.4458
2699                        245.80615,78.31836 242.53467,78.31836 z M
2700                        242.56396,80.41797 C 245.2124,80.41797
2701                        247.46142,81.35156 249.31103,83.21875 C
2702                        251.18115,85.06592 252.11572,87.32227
2703                        252.11572,89.98633 C 252.11572,92.66992
2704                        251.20068,94.89746 249.36963,96.66699 C
2705                        247.4419,98.57275 245.17334,99.52539 242.56397,99.52539
2706                        C 239.9546,99.52539 237.70557,98.58252
2707                        235.81739,96.6958 C 233.92774,94.80957
2708                        232.98389,92.57324 232.98389,89.98633 C
2709                        232.98389,87.3999 233.93799,85.14404 235.84619,83.21875
2710                        C 237.67676,81.35156 239.9165,80.41797
2711                        242.56396,80.41797 z " id="path2848"
2712            style="fill-rule:evenodd"/>
2713          </g>
2714        </g>
2715      </a>
2716      <a id="license-osm-link" xlink:href="http://www.openstreetmap.org/">
2717        <g transform="translate(-210,10)" id="license-osm-text">
2718          <text class="license-text" dx="0" dy="0">
2719            Copyright © <xsl:value-of select="$year"/> OpenStreetMap (openstreetmap.org)
2720          </text>
2721        </g>
2722      </a>
2723      <a id="license-cc-text-link" xlink:href="http://creativecommons.org/licenses/by-sa/2.0/">
2724        <g transform="translate(-150,18)" id="license-cc-text">
2725          <text class="license-text" dx="0" dy="0">This work is licensed under the Creative</text>
2726          <text class="license-text" dx="0" dy="8">Commons Attribution-ShareAlike 2.0 License.</text>
2727          <text class="license-text" dx="0" dy="16">http://creativecommons.org/licenses/by-sa/2.0/</text>
2728        </g>
2729      </a>
2730    </g>
2731  </xsl:template>
2732
2733
2734  <!-- Draw zoom controls -->
2735  <xsl:template name="zoomControl">
2736    <defs>
2737
2738      <style type="text/css">
2739        .fancyButton {
2740        stroke: #8080ff;
2741        stroke-width: 2px;
2742        fill: #fefefe;
2743        }
2744        .fancyButton:hover {
2745        stroke: red;
2746        }
2747      </style>
2748
2749      <filter id="fancyButton" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="350">
2750        <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
2751        <feOffset in="blur" dx="2" dy="2" result="offsetBlur"/>
2752        <feSpecularLighting in="blur" surfaceScale="5" specularConstant=".75" specularExponent="20" lighting-color="white" result="specOut">
2753          <fePointLight x="-5000" y="-10000" z="7000"/>
2754        </feSpecularLighting>
2755        <feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/>
2756        <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
2757        <feMerge>
2758          <feMergeNode in="offsetBlur"/>
2759          <feMergeNode in="litPaint"/>
2760        </feMerge>
2761      </filter>
2762      <symbol id="panDown" viewBox="0 0 19 19" class="fancyButton">
2763        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2764        <path d="M 9.5,5 L 9.5,14"/>
2765      </symbol>
2766      <symbol id="panUp" viewBox="0 0 19 19" class="fancyButton">
2767        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2768        <path d="M 9.5,5 L 9.5,14"/>
2769      </symbol>
2770      <symbol id="panLeft" viewBox="0 0 19 19" class="fancyButton">
2771        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2772        <path d="M 5,9.5 L 14,9.5"/>
2773      </symbol>
2774      <symbol id="panRight" viewBox="0 0 19 19" class="fancyButton">
2775        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2776        <path d="M 5,9.5 L 14,9.5"/>
2777      </symbol>
2778      <symbol id="zoomIn" viewBox="0 0 19 19" class="fancyButton">
2779        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2780        <path d="M 5,9.5 L 14,9.5 M 9.5,5 L 9.5,14"/>
2781      </symbol>
2782      <symbol id="zoomOut" viewBox="0 0 19 19" class="fancyButton">
2783        <path d="M 17 9.5 A 7 7 0 1 1 2,9.5 A 7 7 0 1 1 17 9.5 z"/>
2784        <path d="M 5,9.5 L 14,9.5"/>
2785      </symbol>
2786
2787    </defs>
2788
2789    <g id="gPanDown" filter="url(#fancyButton)" onclick="fnPan('down')">
2790      <use x="18px" y="60px" xlink:href="#panDown" width="14px" height="14px"/>
2791    </g>
2792    <g id="gPanRight" filter="url(#fancyButton)" onclick="fnPan('right')">
2793      <use x="8px" y="70px" xlink:href="#panRight" width="14px" height="14px"/>
2794    </g>
2795    <g id="gPanLeft" filter="url(#fancyButton)" onclick="fnPan('left')">
2796      <use x="28px" y="70px" xlink:href="#panLeft" width="14px" height="14px"/>
2797    </g>
2798    <g id="gPanUp" filter="url(#fancyButton)" onclick="fnPan('up')">
2799      <use x="18px" y="80px" xlink:href="#panUp" width="14px" height="14px"/>
2800    </g>
2801
2802    <xsl:variable name="x1" select="25"/>
2803    <xsl:variable name="y1" select="105"/>
2804    <xsl:variable name="x2" select="25"/>
2805    <xsl:variable name="y2" select="300"/>
2806
2807    <line style="stroke-width: 10; stroke-linecap: butt; stroke: #8080ff;">
2808      <xsl:attribute name="x1">
2809        <xsl:value-of select="$x1"/>
2810      </xsl:attribute>
2811      <xsl:attribute name="y1">
2812        <xsl:value-of select="$y1"/>
2813      </xsl:attribute>
2814      <xsl:attribute name="x2">
2815        <xsl:value-of select="$x2"/>
2816      </xsl:attribute>
2817      <xsl:attribute name="y2">
2818        <xsl:value-of select="$y2"/>
2819      </xsl:attribute>
2820    </line>
2821
2822    <line style="stroke-width: 8; stroke-linecap: butt; stroke: white; stroke-dasharray: 10,1;">
2823      <xsl:attribute name="x1">
2824        <xsl:value-of select="$x1"/>
2825      </xsl:attribute>
2826      <xsl:attribute name="y1">
2827        <xsl:value-of select="$y1"/>
2828      </xsl:attribute>
2829      <xsl:attribute name="x2">
2830        <xsl:value-of select="$x2"/>
2831      </xsl:attribute>
2832      <xsl:attribute name="y2">
2833        <xsl:value-of select="$y2"/>
2834      </xsl:attribute>
2835    </line>
2836
2837    <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
2838    <g id="gZoomIn" filter="url(#fancyButton)" onmousedown="fnZoom('in')">
2839      <use x="15.5px" y="100px" xlink:href="#zoomIn" width="19px" height="19px"/>
2840    </g>
2841
2842    <!-- Need to use onmousedown because onclick is interfered with by the onmousedown handler for panning -->
2843    <g id="gZoomOut" filter="url(#fancyButton)" onmousedown="fnZoom('out')">
2844      <use x="15.5px" y="288px" xlink:href="#zoomOut" width="19px" height="19px"/>
2845    </g>
2846  </xsl:template>
2847
2848  <xsl:template name="javaScript">
2849    <script>
2850      /*
2851
2852      Osmarender
2853
2854      interactive.js
2855
2856      */
2857
2858      function fnResize() {
2859      fnResizeElement("gAttribution")
2860      fnResizeElement("gLicense")
2861      fnResizeElement("gZoomIn")
2862      fnResizeElement("gZoomOut")
2863      }
2864
2865
2866      function fnResizeElement(e) {
2867      //
2868      var oSVG,scale,currentTranslateX,currentTranslateY,oe
2869      //
2870      oSVG=document.rootElement
2871      scale=1/oSVG.currentScale
2872      currentTranslateX=oSVG.currentTranslate.x
2873      currentTranslateY=oSVG.currentTranslate.y
2874      oe=document.getElementById(e)
2875      if (oe) oe.setAttributeNS(null,"transform","scale("+scale+","+scale+") translate("+(-currentTranslateX)+","+(-currentTranslateY)+")")
2876      }
2877
2878
2879      function fnToggleImage(osmImage) {
2880      var xlink = 'http://www.w3.org/1999/xlink';
2881      ogThumbnail=document.getElementById('gThumbnail')
2882      if (ogThumbnail.getAttributeNS(null,"visibility")=="visible") fnHideImage()
2883      else {
2884      ogThumbnail.setAttributeNS(null,"visibility","visible")
2885      oThumbnail=document.getElementById('thumbnail')
2886      oThumbnail.setAttributeNS(xlink,"href",osmImage)
2887      }
2888      }
2889
2890      function fnHideImage() {
2891      ogThumbnail=document.getElementById('gThumbnail')
2892      ogThumbnail.setAttributeNS(null,"visibility","hidden")
2893      }
2894
2895
2896      /* The following code originally written by Jonathan Watt (http://jwatt.org/), Aug. 2005 */
2897
2898      if (!window)
2899      window = this;
2900
2901
2902      function fnOnLoad(evt) {
2903      if (!document) window.document = evt.target.ownerDocument
2904      }
2905
2906
2907      /**
2908      * Event handlers to change the current user space for the zoom and pan
2909      * controls to make them appear to be scale invariant.
2910      */
2911
2912      function fnOnZoom(evt) {
2913      try {
2914      if (evt.newScale == undefined) throw 'bad interface'
2915      // update the transform list that adjusts for zoom and pan
2916      var tlist = document.getElementById('staticElements').transform.baseVal
2917      tlist.getItem(0).setScale(1/evt.newScale, 1/evt.newScale)
2918      tlist.getItem(1).setTranslate(-evt.newTranslate.x, -evt.newTranslate.y)
2919      }
2920      catch (e) {
2921      // work around difficiencies in non-moz implementations (some don't
2922      // implement the SVGZoomEvent or SVGAnimatedTransform interfaces)
2923      var de = document.documentElement
2924      var tform = 'scale(' + 1/de.currentScale + ') ' + 'translate(' + (-de.currentTranslate.x) + ', ' + (-de.currentTranslate.y) + ')'
2925      document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
2926      }
2927      }
2928
2929
2930      function fnOnScroll(evt) {
2931      var ct = document.documentElement.currentTranslate
2932      try {
2933      // update the transform list that adjusts for zoom and pan
2934      var tlist = document.getElementById('staticElements').transform.baseVal
2935      tlist.getItem(1).setTranslate(-ct.x, -ct.y)
2936      }
2937      catch (e) {
2938      // work around difficiencies in non-moz implementations (some don't
2939      // implement the SVGAnimatedTransform interface)
2940      var tform = 'scale(' + 1/document.documentElement.currentScale + ') ' + 'translate(' + (-ct.x) + ', ' + (-ct.y) + ')';
2941      document.getElementById('staticElements').setAttributeNS(null, 'transform', tform)
2942      }
2943      }
2944
2945
2946      function fnZoom(type) {
2947      var de = document.documentElement;
2948      var oldScale = de.currentScale;
2949      var oldTranslate = { x: de.currentTranslate.x, y: de.currentTranslate.y };
2950      var s = 2;
2951      if (type == 'in') {de.currentScale *= 1.5;}
2952      if (type == 'out') {de.currentScale /= 1.4;}
2953      // correct currentTranslate so zooming is to the center of the viewport:
2954
2955      var vp_width, vp_height;
2956      try {
2957      vp_width = de.viewport.width;
2958      vp_height = de.viewport.height;
2959      }
2960      catch (e) {
2961      // work around difficiency in moz ('viewport' property not implemented)
2962      vp_width = window.innerWidth;
2963      vp_height = window.innerHeight;
2964      }
2965      de.currentTranslate.x = vp_width/2 - ((de.currentScale/oldScale) * (vp_width/2 - oldTranslate.x));
2966      de.currentTranslate.y = vp_height/2 - ((de.currentScale/oldScale) * (vp_height/2 - oldTranslate.y));
2967
2968      }
2969
2970
2971      function fnPan(type) {
2972      var de = document.documentElement;
2973      var ct = de.currentTranslate;
2974      var t = 150;
2975      if (type == 'right') ct.x += t;
2976      if (type == 'down') ct.y += t;
2977      if (type == 'left') ct.x -= t;
2978      if (type == 'up') ct.y -= t;
2979      }
2980
2981
2982      var gCurrentX,gCurrentY
2983      var gDeltaX,gDeltaY
2984      var gMouseDown=false
2985      var gCurrentTranslate=document.documentElement.currentTranslate
2986
2987      function fnOnMouseDown(evt) {
2988      gCurrentX=gCurrentTranslate.x
2989      gCurrentY=gCurrentTranslate.y
2990      gDeltaX=evt.clientX
2991      gDeltaY=evt.clientY
2992      gMouseDown=true
2993      evt.target.ownerDocument.rootElement.setAttributeNS(null,"cursor","move")
2994      }
2995
2996
2997      function fnOnMouseUp(evt) {
2998      gMouseDown=false
2999      evt.target.ownerDocument.rootElement.setAttribute("cursor","default")
3000      }
3001
3002
3003      function fnOnMouseMove(evt) {
3004      var id
3005      if (gMouseDown) {
3006      gCurrentTranslate.x=gCurrentX+evt.clientX-gDeltaX
3007      gCurrentTranslate.y=gCurrentY+evt.clientY-gDeltaY
3008      }
3009      }
3010
3011
3012    </script>
3013  </xsl:template>
3014
3015</xsl:stylesheet>
Note: See TracBrowser for help on using the repository browser.