1 <?xml version=
"1.0" encoding=
"UTF-8"?>
3 <!-- monthly_to_commons.xslt - Convert Environment and Climate change Canada
4 historical XML data into a JSON format suitable
6 Copyright (C) 2019-2020 Pierre Choffet
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 <xsl:stylesheet version=
"1.0" xmlns:
xsl=
"http://www.w3.org/1999/XSL/Transform">
23 <xsl:output method=
"text" encoding=
"utf-8" />
25 <xsl:template match=
"/climatedata">
26 <xsl:variable name=
"station-name">
27 <xsl:call-template name=
"camel-case">
28 <xsl:with-param name=
"text" select=
"/climatedata/stationinformation/name/text()" />
31 <xsl:variable name=
"province-name">
32 <xsl:call-template name=
"camel-case">
33 <xsl:with-param name=
"text" select=
"/climatedata/stationinformation/province/text()" />
38 "license": "CC-BY-
4.0",
40 "en": "
</xsl:text><xsl:value-of select=
"$station-name" /><xsl:text> Monthly Weather Data",
41 "fr": "Données météorologiques mensuelles de
</xsl:text><xsl:value-of select=
"$station-name" /><xsl:text>"
43 "sources
": "[https://climate.weather.gc.ca/ Environment and Climate Change Canada]
",
62 "name
": "avgHighTemp
",
65 "ca
": "Mitjana de temps. altes
",
66 "da
": "Gennemsnitlig højeste temperatur
",
67 "de
": "Durchschnittliche Höchsttemperatur
",
68 "en
": "Average high temp
",
69 "es
": "Promedio de temps. altas
",
70 "fr
": "Température maximale moyenne
",
71 "ru
": "Средняя высшая темп
",
72 "sr
": "Просечна виша температура
"
79 "ca
": "Mitjana de temps. baixes
",
80 "da
": "Gennemsnitlige laveste temperatur
",
81 "de
": "Durchschnittliche Tiefsttemperatur
",
82 "en
": "Average low temp
",
83 "es
": "Promedio de temps. bajas
",
84 "fr
": "Température minimale moyenne
",
85 "ru
": "Средняя нижняя темп
",
86 "sr
": "Просечна нижа температура
"
93 "en
": "Average temperature
",
94 "fr
": "Température moyenne
"
98 "name
": "extHighTemp
",
101 "en
": "Highest daily maximum temperature
",
102 "fr
": "Température maximale quotidienne la plus élevée
"
106 "name
": "extLowTemp
",
109 "en
": "Lowest daily minimal temperature
",
110 "fr
": "Température minimale la plus basse
"
114 "name
": "precipTotalRain
",
117 "en
": "Total rainfall (mm)
",
118 "fr
": "Pluie totale (mm)
"
122 "name
": "precipTotalSnow
",
125 "en
": "Total snowfall (cm)
",
126 "fr
": "Neige totale (cm)
"
130 "name
": "precipTotal
",
133 "en
": "Total précipitation (mm)
",
134 "fr
": "Précipitations totale (mm)
"
138 "name
": "snowGrndLastDay
",
141 "en
": "Snow on the ground on the last day (cm)
",
142 "fr
": "Neige au sol le dernier jour (cm)
"
146 "name
": "windDirMaxGust
",
149 "en
": "Direction of maximum gust (
10's deg/tens of degrees)
",
150 "fr
": "Direction de la rafale maximale (
10's deg/dizaines de degrés)
"
154 "name
": "windSpeedMaxGust
",
157 "en
": "Speed of maximum gust (km/h)
",
158 "fr
": "Vitesse de la rafale maximale (km/h)
"
164 <xsl:apply-templates select="stationdata
" />
165 <xsl:text>]}</xsl:text>
168 <xsl:template match="stationdata
">
169 <!-- TODO: Check element has at least one data? -->
171 <xsl:text>["</xsl:text>
172 <xsl:value-of select=
"@year" />
173 <xsl:text>-
</xsl:text>
174 <xsl:value-of select=
"format-number(@month, '00')" />
175 <xsl:text>"</xsl:text>
177 <!-- Set meanmaxtemp -->
178 <xsl:text>, </xsl:text>
179 <xsl:apply-templates select="meanmaxtemp
" />
181 <!-- Set meanmintemp -->
182 <xsl:text>, </xsl:text>
183 <xsl:apply-templates select="meanmintemp
" />
185 <!-- Set meanmonthtemp -->
186 <xsl:text>, </xsl:text>
187 <xsl:apply-templates select="meanmonthtemp
" />
189 <!-- Set extrmaxtemp -->
190 <xsl:text>, </xsl:text>
191 <xsl:apply-templates select="extrmaxtemp
" />
193 <!-- Set extrmintemp -->
194 <xsl:text>, </xsl:text>
195 <xsl:apply-templates select="extrmintemp
" />
198 <xsl:text>, </xsl:text>
199 <xsl:apply-templates select="totrain
" />
202 <xsl:text>, </xsl:text>
203 <xsl:apply-templates select="totsnow
" />
205 <!-- Set totprecip -->
206 <xsl:text>, </xsl:text>
207 <xsl:apply-templates select="totprecip
" />
209 <!-- Set grndsnowlastday -->
210 <xsl:text>, </xsl:text>
211 <xsl:apply-templates select="grndsnowlastday
" />
213 <!-- Set dirmaxgust -->
214 <xsl:text>, </xsl:text>
215 <xsl:apply-templates select="dirmaxgust
" />
217 <!-- Set speedmaxgust -->
218 <xsl:text>, </xsl:text>
219 <xsl:apply-templates select="speedmaxgust
" />
222 <xsl:text>]</xsl:text>
223 <xsl:if test="position() != last()
">
224 <xsl:text>, </xsl:text>
228 <!-- Process meanmaxtemp -->
229 <xsl:template match="meanmaxtemp
">
231 <xsl:when test="not(text())
">
232 <xsl:text>null</xsl:text>
234 <xsl:when test="@flag = 'E'
">
235 <xsl:message>WARNING: <xsl:value-of select="../@year
" />-<xsl:value-of select="format-number(../@month, '
00')
" />: Insert estimated meanmaxtemp value</xsl:message>
236 <xsl:value-of select="text()
" />
238 <xsl:when test="@flag = 'I'
">
239 <xsl:message>WARNING: <xsl:value-of select="../@year
" />-<xsl:value-of select="format-number(../@month, '
00')
" />: Insert meanmaxtemp value with undocumented "I" flag
</xsl:message>
240 <xsl:value-of select=
"text()" />
242 <xsl:when test=
"@flag = 'M'">
243 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available meanmaxtemp marked as missing
</xsl:message>
244 <xsl:value-of select=
"text()" />
247 <xsl:value-of select=
"text()" />
252 <!-- Process meanmintemp -->
253 <xsl:template match=
"meanmintemp">
255 <xsl:when test=
"not(text())">
256 <xsl:text>null
</xsl:text>
258 <xsl:when test=
"@flag = 'E'">
259 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated meanmintemp value
</xsl:message>
260 <xsl:value-of select=
"text()" />
262 <xsl:when test=
"@flag = 'I'">
263 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert meanmintemp value with undocumented "I" flag
</xsl:message>
264 <xsl:value-of select=
"text()" />
266 <xsl:when test=
"@flag = 'M'">
267 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available meanmintemp marked as missing
</xsl:message>
268 <xsl:value-of select=
"text()" />
271 <xsl:value-of select=
"text()" />
276 <!-- Process meanmonthtemp -->
277 <xsl:template match=
"meanmonthtemp">
279 <xsl:when test=
"not(text())">
280 <xsl:text>null
</xsl:text>
282 <xsl:when test=
"@flag = 'E'">
283 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated meanmonthtemp value
</xsl:message>
284 <xsl:value-of select=
"text()" />
286 <xsl:when test=
"@flag = 'I'">
287 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert meanmonthtemp value with undocumented "I" flag
</xsl:message>
288 <xsl:value-of select=
"text()" />
290 <xsl:when test=
"@flag = 'M'">
291 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available meanmonthtemp marked as missing
</xsl:message>
292 <xsl:value-of select=
"text()" />
295 <xsl:value-of select=
"text()" />
300 <!-- Process extrmaxtemp -->
301 <xsl:template match=
"extrmaxtemp">
303 <xsl:when test=
"not(text())">
304 <xsl:text>null
</xsl:text>
306 <xsl:when test=
"@flag = 'B'">
307 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert multiple and estimated extrmaxtemp value
</xsl:message>
308 <xsl:value-of select=
"text()" />
310 <xsl:when test=
"@flag = 'E'">
311 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated extrmaxtemp value
</xsl:message>
312 <xsl:value-of select=
"text()" />
314 <xsl:when test=
"@flag = 'I'">
315 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert extrmaxtemp value with undocumented "I" flag
</xsl:message>
316 <xsl:value-of select=
"text()" />
318 <xsl:when test=
"@flag = 'M'">
319 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available extrmaxtemp marked as missing
</xsl:message>
320 <xsl:value-of select=
"text()" />
322 <xsl:when test=
"@flag = 'S'">
323 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert multiple extrmaxtemp value
</xsl:message>
324 <xsl:value-of select=
"text()" />
327 <xsl:value-of select=
"text()" />
332 <!-- Process extrmintemp -->
333 <xsl:template match=
"extrmintemp">
335 <xsl:when test=
"not(text())">
336 <xsl:text>null
</xsl:text>
338 <xsl:when test=
"@flag = 'B'">
339 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert multiple and estimated extrmintemp value
</xsl:message>
340 <xsl:value-of select=
"text()" />
342 <xsl:when test=
"@flag = 'E'">
343 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated extrmintemp value
</xsl:message>
344 <xsl:value-of select=
"text()" />
346 <xsl:when test=
"@flag = 'I'">
347 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert extrmintemp value with undocumented "I" flag
</xsl:message>
348 <xsl:value-of select=
"text()" />
350 <xsl:when test=
"@flag = 'M'">
351 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available extrmintemp marked as missing
</xsl:message>
352 <xsl:value-of select=
"text()" />
354 <xsl:when test=
"@flag = 'S'">
355 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert multiple extrmintemp value
</xsl:message>
356 <xsl:value-of select=
"text()" />
359 <xsl:value-of select=
"text()" />
364 <!-- Process totrain -->
365 <xsl:template match=
"totrain">
367 <xsl:when test=
"not(text())">
368 <xsl:text>null
</xsl:text>
370 <xsl:when test=
"contains(text(), '#')">
371 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Discard totrain containing "#"
</xsl:message>
372 <xsl:text>null
</xsl:text>
374 <xsl:when test=
"@flag = 'E'">
375 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated totrain value
</xsl:message>
376 <xsl:value-of select=
"text()" />
378 <xsl:when test=
"@flag = 'I'">
379 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert totrain value with undocumented "I" flag
</xsl:message>
380 <xsl:value-of select=
"text()" />
382 <xsl:when test=
"@flag = 'M'">
383 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available totrain marked as missing
</xsl:message>
384 <xsl:value-of select=
"text()" />
386 <xsl:when test=
"@flag = 'T'">
387 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert traces only totrain value
</xsl:message>
388 <xsl:value-of select=
"text()" />
391 <xsl:value-of select=
"text()" />
396 <!-- Process totsnow -->
397 <xsl:template match=
"totsnow">
399 <xsl:when test=
"not(text())">
400 <xsl:text>null
</xsl:text>
402 <xsl:when test=
"text() < 0">
403 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Discard negative totsnow value
</xsl:message>
404 <xsl:text>null
</xsl:text>
406 <xsl:when test=
"@flag = 'E'">
407 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated totsnow value
</xsl:message>
408 <xsl:value-of select=
"text()" />
410 <xsl:when test=
"@flag = 'I'">
411 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert totsnow value with undocumented "I" flag
</xsl:message>
412 <xsl:value-of select=
"text()" />
414 <xsl:when test=
"@flag = 'M'">
415 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available totsnow marked as missing
</xsl:message>
416 <xsl:value-of select=
"text()" />
418 <xsl:when test=
"@flag = 'T'">
419 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert traces only totsnow value
</xsl:message>
420 <xsl:value-of select=
"text()" />
423 <xsl:value-of select=
"text()" />
428 <!-- Process totprecip -->
429 <xsl:template match=
"totprecip">
431 <xsl:when test=
"not(text())">
432 <xsl:text>null
</xsl:text>
434 <xsl:when test=
"contains(text(), '#')">
435 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Discard totprecip containing "#"
</xsl:message>
436 <xsl:text>null
</xsl:text>
438 <xsl:when test=
"@flag = 'E'">
439 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated totprecip value
</xsl:message>
440 <xsl:value-of select=
"text()" />
442 <xsl:when test=
"@flag = 'I'">
443 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert totprecip value with undocumented "I" flag
</xsl:message>
444 <xsl:value-of select=
"text()" />
446 <xsl:when test=
"@flag = 'M'">
447 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available totprecip marked as missing
</xsl:message>
448 <xsl:value-of select=
"text()" />
450 <xsl:when test=
"@flag = 'T'">
451 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert traces only totprecip value
</xsl:message>
452 <xsl:value-of select=
"text()" />
455 <xsl:value-of select=
"text()" />
460 <!-- Process grndsnowlastday -->
461 <xsl:template match=
"grndsnowlastday">
463 <xsl:when test=
"not(text())">
464 <xsl:text>null
</xsl:text>
466 <xsl:when test=
"@flag = 'E'">
467 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated grndsnowlastday value
</xsl:message>
468 <xsl:value-of select=
"text()" />
470 <xsl:when test=
"@flag = 'M'">
471 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available grndsnowlastday marked as missing
</xsl:message>
472 <xsl:value-of select=
"text()" />
474 <xsl:when test=
"@flag = 'T'">
475 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert traces only grndsnowlastday value
</xsl:message>
476 <xsl:value-of select=
"text()" />
479 <xsl:value-of select=
"text()" />
484 <!-- Process dirmaxgust -->
485 <xsl:template match=
"dirmaxgust">
487 <xsl:when test=
"not(text())">
488 <xsl:text>null
</xsl:text>
490 <xsl:when test=
"@flag = 'B'">
491 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert multiple and estimated dirmaxgust value
</xsl:message>
492 <xsl:value-of select=
"text()" />
494 <xsl:when test=
"@flag = 'E'">
495 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated dirmaxgust value
</xsl:message>
496 <xsl:value-of select=
"text()" />
498 <xsl:when test=
"@flag = 'I'">
499 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert dirmaxgust value with undocumented "I" flag
</xsl:message>
500 <xsl:value-of select=
"text()" />
502 <xsl:when test=
"@flag = 'M'">
503 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available dirmaxgust marked as missing
</xsl:message>
504 <xsl:value-of select=
"text()" />
506 <xsl:when test=
"@flag = 'S'">
507 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert multiple dirmaxgust value
</xsl:message>
508 <xsl:value-of select=
"text()" />
510 <xsl:when test=
"text() = '36'">
511 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert dirmaxgust with a value of "
36"
</xsl:message>
512 <xsl:value-of select=
"text()" />
515 <xsl:value-of select=
"text()" />
520 <!-- Process speedmaxgust -->
521 <xsl:template match=
"speedmaxgust">
523 <xsl:when test=
"not(text())">
524 <xsl:text>null
</xsl:text>
526 <xsl:when test=
"text() = '<31'">
527 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Discard speedmaxgust with value "
<31"
</xsl:message>
528 <xsl:text>null
</xsl:text>
530 <xsl:when test=
"@flag = 'B'">
531 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert multiple and estimated speedmaxgust value
</xsl:message>
532 <xsl:value-of select=
"text()" />
534 <xsl:when test=
"@flag = 'E'">
535 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert estimated speedmaxgust value
</xsl:message>
536 <xsl:value-of select=
"text()" />
538 <xsl:when test=
"@flag = 'I'">
539 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert speedmaxgust value with undocumented "I" flag
</xsl:message>
540 <xsl:value-of select=
"text()" />
542 <xsl:when test=
"@flag = 'M'">
543 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert available speedmaxgust marked as missing
</xsl:message>
544 <xsl:value-of select=
"text()" />
546 <xsl:when test=
"@flag = 'S'">
547 <xsl:message>WARNING:
<xsl:value-of select=
"../@year" />-
<xsl:value-of select=
"format-number(../@month, '00')" />: Insert multiple speedmaxgust value
</xsl:message>
548 <xsl:value-of select=
"text()" />
551 <xsl:value-of select=
"text()" />
557 <xsl:template name=
"camel-case">
558 <xsl:param name=
"text" select=
"."/>
559 <xsl:variable name=
"uppercase">ABCDEFGHIJKLMNOPQRSTUVWXYZ
</xsl:variable>
560 <xsl:variable name=
"lowercase">abcdefghijklmnopqrstuvwxyz
</xsl:variable>
561 <xsl:variable name=
"word" select=
"substring-before(concat($text, ' '), ' ')" />
563 <xsl:value-of select=
"translate(substring($word, 1, 1), $lowercase, $uppercase)" />
564 <xsl:value-of select=
"translate(substring($word, 2), $uppercase, $lowercase)" />
566 <xsl:if test=
"contains($text, ' ')">
567 <xsl:text> </xsl:text>
568 <xsl:call-template name=
"camel-case">
569 <xsl:with-param name=
"text" select=
"substring-after($text, ' ')"/>