]> Wikimedia Canada | Git repositories - eccc_to_commons.git/blob - almanac_to_commons.xslt
Licence change
[eccc_to_commons.git] / almanac_to_commons.xslt
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <!-- almanac_to_commons.xslt - Convert Environment and Climate change Canada
4 historical XML data into a JSON format suitable
5 for Wikimedia Commons.
6 Copyright (C) 2019-2020 Pierre Choffet
7
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.
12
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.
17
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/>.
20 -->
21
22 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
23 <xsl:output method="text" encoding="utf-8" />
24
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()" />
29 </xsl:call-template>
30 </xsl:variable>
31 <xsl:variable name="province-name">
32 <xsl:call-template name="camel-case">
33 <xsl:with-param name="text" select="/climatedata/stationinformation/province/text()" />
34 </xsl:call-template>
35 </xsl:variable>
36
37 <xsl:text>{
38 "license": "CC-BY-4.0",
39 "description": {
40 "en": "</xsl:text><xsl:value-of select="$station-name" /><xsl:text> average and extreme data",
41 "fr": "Moyennes et extrêmes pour la station météorologique </xsl:text><xsl:value-of select="$station-name" /><xsl:text>"
42 },
43 "sources": "[https://climate.weather.gc.ca/ Environment and Climate Change Canada]",
44 "wikicode": "[Category:Environment and Climate Change Canada Almanac Data] [Category:Weather Data in </xsl:text>
45 <xsl:value-of select="$province-name" />
46 <xsl:text>]",
47 "schema": {
48 "fields": [
49 {
50 "name": "date",
51 "type": "string",
52 "title": {
53 "ar": "تاريخ",
54 "ca": "Data",
55 "da": "Dato",
56 "de": "Datum",
57 "en": "Date",
58 "es": "Fecha",
59 "fr": "Date",
60 "ru": "Дата",
61 "sr": "Датум"
62 }
63 },
64 {
65 "name": "extremeMax",
66 "type": "number",
67 "title": {
68 "en": "Highest maximum temperature",
69 "fr": "Température maximale la plus élevée"
70 }
71 },
72 {
73 "name": "extremeMin",
74 "type": "number",
75 "title": {
76 "en": "Lowest minimum temperature",
77 "fr": "Température minimale la plus basse"
78 }
79 },
80 {
81 "name": "normalMax",
82 "type": "number",
83 "title": {
84 "en": "Highest normal temperature",
85 "fr": "Température normale haute"
86 }
87 },
88 {
89 "name": "normalMin",
90 "type": "number",
91 "title": {
92 "en": "Lowest normal temperature",
93 "fr": "Température normale basse"
94 }
95 },
96 {
97 "name": "normalMean",
98 "type": "number",
99 "title": {
100 "en": "Mean normal temperature",
101 "fr": "Température normale moyenne"
102 }
103 },
104 {
105 "name": "extremeRainfall",
106 "type": "number",
107 "title": {
108 "en": "Greatest rainfall",
109 "fr": "Pluie maximale"
110 }
111 },
112 {
113 "name": "extremeSnowfall",
114 "type": "number",
115 "title": {
116 "en": "Greatest snowfall",
117 "fr": "Neige maximale"
118 }
119 },
120 {
121 "name": "extremePrecipitation",
122 "type": "number",
123 "title": {
124 "en": "Greatest precipitation",
125 "fr": "Précipitation maximale"
126 }
127 },
128 {
129 "name": "extremeSnowOnGround",
130 "type": "number",
131 "title": {
132 "en": "Most snow on the ground",
133 "fr": "Maximum de neige au sol"
134 }
135 },
136 {
137 "name": "pop",
138 "type": "number",
139 "title": {
140 "en": "Monthly frequency of precipitation",
141 "fr": "Fréquence mensuelle de précipitation"
142 }
143 }
144 ]
145 },
146 "data": [</xsl:text>
147 <xsl:apply-templates select="month" />
148 <xsl:text>]}</xsl:text>
149 </xsl:template>
150
151 <xsl:template match="month">
152 <!-- TODO: Check element has at least one data? -->
153 <xsl:apply-templates select="day">
154 <xsl:with-param name="month" select="format-number(@index, '00')" />
155 </xsl:apply-templates>
156 <xsl:if test="day and following-sibling::month[day]">
157 <xsl:text>, </xsl:text>
158 </xsl:if>
159 </xsl:template>
160
161 <xsl:template match="day">
162 <xsl:param name="month" />
163 <xsl:param name="day" select="format-number(@index, '00')" />
164
165 <xsl:text>["</xsl:text>
166 <xsl:value-of select="$month" />-<xsl:value-of select="$day" />
167 <xsl:text>"</xsl:text>
168
169 <!-- Set extremeMax -->
170 <xsl:text>, </xsl:text>
171 <xsl:apply-templates select="temperature[@class = 'extremeMax']">
172 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
173 </xsl:apply-templates>
174
175 <!-- Set extremeMin -->
176 <xsl:text>, </xsl:text>
177 <xsl:apply-templates select="temperature[@class = 'extremeMin']">
178 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
179 </xsl:apply-templates>
180
181 <!-- Set normalMax -->
182 <xsl:text>, </xsl:text>
183 <xsl:apply-templates select="temperature[@class = 'normalMax']">
184 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
185 </xsl:apply-templates>
186
187 <!-- Set normalMin -->
188 <xsl:text>, </xsl:text>
189 <xsl:apply-templates select="temperature[@class = 'normalMin']">
190 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
191 </xsl:apply-templates>
192
193 <!-- Set normalMean -->
194 <xsl:text>, </xsl:text>
195 <xsl:apply-templates select="temperature[@class = 'normalMean']">
196 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
197 </xsl:apply-templates>
198
199 <!-- Set extremeRainfall -->
200 <xsl:text>, </xsl:text>
201 <xsl:apply-templates select="precipitation[@class = 'extremeRainfall']">
202 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
203 </xsl:apply-templates>
204
205 <!-- Set extremeSnowfall -->
206 <xsl:text>, </xsl:text>
207 <xsl:apply-templates select="precipitation[@class = 'extremeSnowfall']">
208 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
209 </xsl:apply-templates>
210
211 <!-- Set extremePrecipitation -->
212 <xsl:text>, </xsl:text>
213 <xsl:apply-templates select="precipitation[@class = 'extremePrecipitation']">
214 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
215 </xsl:apply-templates>
216
217 <!-- Set extremeSnowOnGround -->
218 <xsl:text>, </xsl:text>
219 <xsl:apply-templates select="precipitation[@class = 'extremeSnowOnGround']">
220 <xsl:with-param name="date"><xsl:value-of select="$month" />-<xsl:value-of select="$day" /></xsl:with-param>
221 </xsl:apply-templates>
222
223 <!-- Set pop -->
224 <!-- WARNING: This is not daily data, it makes no sense to have it in final dataset -->
225 <xsl:text>, </xsl:text>
226 <xsl:apply-templates select="pop" />
227
228 <xsl:text>]</xsl:text>
229 <xsl:if test="position() != last()">
230 <xsl:text>, </xsl:text>
231 </xsl:if>
232 </xsl:template>
233
234 <xsl:template match="temperature[@class = 'extremeMax']">
235 <xsl:param name="date" />
236
237 <xsl:choose>
238 <xsl:when test="not(text())">
239 <xsl:text>null</xsl:text>
240 </xsl:when>
241 <xsl:when test="@quality = '†'">
242 <xsl:message>WARNING: <xsl:value-of select="$date" />: Insert not reviewed extremeMax value</xsl:message>
243 <xsl:value-of select="text()" />
244 </xsl:when>
245 <xsl:otherwise>
246 <xsl:value-of select="text()" />
247 </xsl:otherwise>
248 </xsl:choose>
249 </xsl:template>
250
251 <xsl:template match="temperature[@class = 'extremeMin']">
252 <xsl:param name="date" />
253
254 <xsl:choose>
255 <xsl:when test="not(text())">
256 <xsl:text>null</xsl:text>
257 </xsl:when>
258 <xsl:when test="@quality = '†'">
259 <xsl:message>WARNING: <xsl:value-of select="$date" />: Insert not reviewed extremeMin value</xsl:message>
260 <xsl:value-of select="text()" />
261 </xsl:when>
262 <xsl:otherwise>
263 <xsl:value-of select="text()" />
264 </xsl:otherwise>
265 </xsl:choose>
266 </xsl:template>
267
268 <xsl:template match="temperature[@class = 'normalMax']">
269 <xsl:param name="date" />
270
271 <xsl:choose>
272 <xsl:when test="not(text())">
273 <xsl:text>null</xsl:text>
274 </xsl:when>
275 <xsl:when test="@quality = '†'">
276 <xsl:message terminate="yes">normalMax value not reviewed</xsl:message>
277 </xsl:when>
278 <xsl:otherwise>
279 <xsl:value-of select="text()" />
280 </xsl:otherwise>
281 </xsl:choose>
282 </xsl:template>
283
284 <xsl:template match="temperature[@class = 'normalMin']">
285 <xsl:param name="date" />
286
287 <xsl:choose>
288 <xsl:when test="not(text())">
289 <xsl:text>null</xsl:text>
290 </xsl:when>
291 <xsl:when test="@quality = '†'">
292 <xsl:message terminate="yes">normalMin value not reviewed</xsl:message>
293 </xsl:when>
294 <xsl:otherwise>
295 <xsl:value-of select="text()" />
296 </xsl:otherwise>
297 </xsl:choose>
298 </xsl:template>
299
300 <xsl:template match="temperature[@class = 'normalMean']">
301 <xsl:param name="date" />
302
303 <xsl:choose>
304 <xsl:when test="not(text())">
305 <xsl:text>null</xsl:text>
306 </xsl:when>
307 <xsl:when test="@quality = '†'">
308 <xsl:message terminate="yes">normalMean value not reviewed</xsl:message>
309 </xsl:when>
310 <xsl:otherwise>
311 <xsl:value-of select="text()" />
312 </xsl:otherwise>
313 </xsl:choose>
314 </xsl:template>
315
316 <xsl:template match="precipitation[@class = 'extremeRainfall']">
317 <xsl:param name="date" />
318
319 <xsl:choose>
320 <xsl:when test="not(text())">
321 <xsl:text>null</xsl:text>
322 </xsl:when>
323 <xsl:when test="@quality = '†'">
324 <xsl:message>WARNING: <xsl:value-of select="$date" />: Insert not reviewed extremeRainfall value</xsl:message>
325 <xsl:value-of select="text()" />
326 </xsl:when>
327 <xsl:otherwise>
328 <xsl:value-of select="text()" />
329 </xsl:otherwise>
330 </xsl:choose>
331 </xsl:template>
332
333 <xsl:template match="precipitation[@class = 'extremeSnowfall']">
334 <xsl:param name="date" />
335
336 <xsl:choose>
337 <xsl:when test="not(text())">
338 <xsl:text>null</xsl:text>
339 </xsl:when>
340 <xsl:when test="@quality = '†'">
341 <xsl:message>WARNING: <xsl:value-of select="$date" />: Insert not reviewed extremeSnowfall value</xsl:message>
342 <xsl:value-of select="text()" />
343 </xsl:when>
344 <xsl:otherwise>
345 <xsl:value-of select="text()" />
346 </xsl:otherwise>
347 </xsl:choose>
348 </xsl:template>
349
350 <xsl:template match="precipitation[@class = 'extremePrecipitation']">
351 <xsl:param name="date" />
352
353 <xsl:choose>
354 <xsl:when test="not(text())">
355 <xsl:text>null</xsl:text>
356 </xsl:when>
357 <xsl:when test="@quality = '†'">
358 <xsl:message>WARNING: <xsl:value-of select="$date" />: Insert not reviewed extremePrecipitation value</xsl:message>
359 <xsl:value-of select="text()" />
360 </xsl:when>
361 <xsl:otherwise>
362 <xsl:value-of select="text()" />
363 </xsl:otherwise>
364 </xsl:choose>
365 </xsl:template>
366
367 <xsl:template match="precipitation[@class = 'extremeSnowOnGround']">
368 <xsl:param name="date" />
369
370 <xsl:choose>
371 <xsl:when test="not(text())">
372 <xsl:text>null</xsl:text>
373 </xsl:when>
374 <xsl:when test="contains(text(), '#')">
375 <xsl:message>WARNING: <xsl:value-of select="$date" />: Discard extremeSnowOnGround containing "#"</xsl:message>
376 <xsl:text>null</xsl:text>
377 </xsl:when>
378 <xsl:when test="@quality = '†'">
379 <xsl:message>WARNING: <xsl:value-of select="$date" />: Insert not reviewed extremeSnowOnGround value</xsl:message>
380 <xsl:value-of select="text()" />
381 </xsl:when>
382 <xsl:otherwise>
383 <xsl:value-of select="text()" />
384 </xsl:otherwise>
385 </xsl:choose>
386 </xsl:template>
387
388 <xsl:template match="pop">
389 <xsl:param name="date" />
390
391 <xsl:choose>
392 <xsl:when test="not(text())">
393 <xsl:text>null</xsl:text>
394 </xsl:when>
395 <xsl:when test="@quality = '†'">
396 <xsl:message terminate="yes">pop value not reviewed</xsl:message>
397 </xsl:when>
398 <xsl:otherwise>
399 <xsl:value-of select="text()" />
400 </xsl:otherwise>
401 </xsl:choose>
402 </xsl:template>
403
404 <!-- Camel case -->
405 <xsl:template name="camel-case">
406 <xsl:param name="text" select="."/>
407 <xsl:variable name="uppercase">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
408 <xsl:variable name="lowercase">abcdefghijklmnopqrstuvwxyz</xsl:variable>
409 <xsl:variable name="word" select="substring-before(concat($text, ' '), ' ')" />
410
411 <xsl:value-of select="translate(substring($word, 1, 1), $lowercase, $uppercase)" />
412 <xsl:value-of select="translate(substring($word, 2), $uppercase, $lowercase)" />
413
414 <xsl:if test="contains($text, ' ')">
415 <xsl:text> </xsl:text>
416 <xsl:call-template name="camel-case">
417 <xsl:with-param name="text" select="substring-after($text, ' ')"/>
418 </xsl:call-template>
419 </xsl:if>
420 </xsl:template>
421 </xsl:stylesheet>