1 <?xml version=
"1.0" encoding=
"UTF-8"?>
3 <!-- almanac_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> 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>"
43 "sources
": "[https://climate.weather.gc.ca/ Environment and Climate Change Canada]
",
65 "en
": "Highest maximum temperature
",
66 "fr
": "Température maximale la plus élevée
"
73 "en
": "Lowest minimum temperature
",
74 "fr
": "Température minimale la plus basse
"
81 "en
": "Highest normal temperature
",
82 "fr
": "Température normale haute
"
89 "en
": "Lowest normal temperature
",
90 "fr
": "Température normale basse
"
97 "en
": "Mean normal temperature
",
98 "fr
": "Température normale moyenne
"
102 "name
": "extremeRainfall
",
105 "en
": "Greatest rainfall
",
106 "fr
": "Pluie maximale
"
110 "name
": "extremeSnowfall
",
113 "en
": "Greatest snowfall
",
114 "fr
": "Neige maximale
"
118 "name
": "extremePrecipitation
",
121 "en
": "Greatest precipitation
",
122 "fr
": "Précipitation maximale
"
126 "name
": "extremeSnowOnGround
",
129 "en
": "Most snow on the ground
",
130 "fr
": "Maximum de neige au sol
"
137 "en
": "Monthly frequency of precipitation
",
138 "fr
": "Fréquence mensuelle de précipitation
"
144 <xsl:apply-templates select="month
" />
145 <xsl:text>]}</xsl:text>
148 <xsl:template match="month
">
149 <!-- TODO: Check element has at least one data? -->
150 <xsl:apply-templates select="day
">
151 <xsl:with-param name="month
" select="format-number(@index, '
00')
" />
152 </xsl:apply-templates>
153 <xsl:if test="day and following-sibling::month[day]
">
154 <xsl:text>, </xsl:text>
158 <xsl:template match="day
">
159 <xsl:param name="month
" />
160 <xsl:param name="day
" select="format-number(@index, '
00')
" />
162 <xsl:text>["</xsl:text>
163 <xsl:value-of select=
"$month" />-
<xsl:value-of select=
"$day" />
164 <xsl:text>"</xsl:text>
166 <!-- Set extremeMax -->
167 <xsl:text>, </xsl:text>
168 <xsl:apply-templates select="temperature[@class = 'extremeMax']
">
169 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
170 </xsl:apply-templates>
172 <!-- Set extremeMin -->
173 <xsl:text>, </xsl:text>
174 <xsl:apply-templates select="temperature[@class = 'extremeMin']
">
175 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
176 </xsl:apply-templates>
178 <!-- Set normalMax -->
179 <xsl:text>, </xsl:text>
180 <xsl:apply-templates select="temperature[@class = 'normalMax']
">
181 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
182 </xsl:apply-templates>
184 <!-- Set normalMin -->
185 <xsl:text>, </xsl:text>
186 <xsl:apply-templates select="temperature[@class = 'normalMin']
">
187 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
188 </xsl:apply-templates>
190 <!-- Set normalMean -->
191 <xsl:text>, </xsl:text>
192 <xsl:apply-templates select="temperature[@class = 'normalMean']
">
193 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
194 </xsl:apply-templates>
196 <!-- Set extremeRainfall -->
197 <xsl:text>, </xsl:text>
198 <xsl:apply-templates select="precipitation[@class = 'extremeRainfall']
">
199 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
200 </xsl:apply-templates>
202 <!-- Set extremeSnowfall -->
203 <xsl:text>, </xsl:text>
204 <xsl:apply-templates select="precipitation[@class = 'extremeSnowfall']
">
205 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
206 </xsl:apply-templates>
208 <!-- Set extremePrecipitation -->
209 <xsl:text>, </xsl:text>
210 <xsl:apply-templates select="precipitation[@class = 'extremePrecipitation']
">
211 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
212 </xsl:apply-templates>
214 <!-- Set extremeSnowOnGround -->
215 <xsl:text>, </xsl:text>
216 <xsl:apply-templates select="precipitation[@class = 'extremeSnowOnGround']
">
217 <xsl:with-param name="date
"><xsl:value-of select="$month
" />-<xsl:value-of select="$day
" /></xsl:with-param>
218 </xsl:apply-templates>
221 <!-- WARNING: This is not daily data, it makes no sense to have it in final dataset -->
222 <xsl:text>, </xsl:text>
223 <xsl:apply-templates select="pop
" />
225 <xsl:text>]</xsl:text>
226 <xsl:if test="position() != last()
">
227 <xsl:text>, </xsl:text>
231 <xsl:template match="temperature[@class = 'extremeMax']
">
232 <xsl:param name="date
" />
235 <xsl:when test="not(text())
">
236 <xsl:text>null</xsl:text>
238 <xsl:when test="@quality = '†'
">
239 <xsl:message>WARNING: <xsl:value-of select="$date
" />: Insert not reviewed extremeMax value</xsl:message>
240 <xsl:value-of select="text()
" />
243 <xsl:value-of select="text()
" />
248 <xsl:template match="temperature[@class = 'extremeMin']
">
249 <xsl:param name="date
" />
252 <xsl:when test="not(text())
">
253 <xsl:text>null</xsl:text>
255 <xsl:when test="@quality = '†'
">
256 <xsl:message>WARNING: <xsl:value-of select="$date
" />: Insert not reviewed extremeMin value</xsl:message>
257 <xsl:value-of select="text()
" />
260 <xsl:value-of select="text()
" />
265 <xsl:template match="temperature[@class = 'normalMax']
">
266 <xsl:param name="date
" />
269 <xsl:when test="not(text())
">
270 <xsl:text>null</xsl:text>
272 <xsl:when test="@quality = '†'
">
273 <xsl:message terminate="yes
">normalMax value not reviewed</xsl:message>
276 <xsl:value-of select="text()
" />
281 <xsl:template match="temperature[@class = 'normalMin']
">
282 <xsl:param name="date
" />
285 <xsl:when test="not(text())
">
286 <xsl:text>null</xsl:text>
288 <xsl:when test="@quality = '†'
">
289 <xsl:message terminate="yes
">normalMin value not reviewed</xsl:message>
292 <xsl:value-of select="text()
" />
297 <xsl:template match="temperature[@class = 'normalMean']
">
298 <xsl:param name="date
" />
301 <xsl:when test="not(text())
">
302 <xsl:text>null</xsl:text>
304 <xsl:when test="@quality = '†'
">
305 <xsl:message terminate="yes
">normalMean value not reviewed</xsl:message>
308 <xsl:value-of select="text()
" />
313 <xsl:template match="precipitation[@class = 'extremeRainfall']
">
314 <xsl:param name="date
" />
317 <xsl:when test="not(text())
">
318 <xsl:text>null</xsl:text>
320 <xsl:when test="@quality = '†'
">
321 <xsl:message>WARNING: <xsl:value-of select="$date
" />: Insert not reviewed extremeRainfall value</xsl:message>
322 <xsl:value-of select="text()
" />
325 <xsl:value-of select="text()
" />
330 <xsl:template match="precipitation[@class = 'extremeSnowfall']
">
331 <xsl:param name="date
" />
334 <xsl:when test="not(text())
">
335 <xsl:text>null</xsl:text>
337 <xsl:when test="@quality = '†'
">
338 <xsl:message>WARNING: <xsl:value-of select="$date
" />: Insert not reviewed extremeSnowfall value</xsl:message>
339 <xsl:value-of select="text()
" />
342 <xsl:value-of select="text()
" />
347 <xsl:template match="precipitation[@class = 'extremePrecipitation']
">
348 <xsl:param name="date
" />
351 <xsl:when test="not(text())
">
352 <xsl:text>null</xsl:text>
354 <xsl:when test="@quality = '†'
">
355 <xsl:message>WARNING: <xsl:value-of select="$date
" />: Insert not reviewed extremePrecipitation value</xsl:message>
356 <xsl:value-of select="text()
" />
359 <xsl:value-of select="text()
" />
364 <xsl:template match="precipitation[@class = 'extremeSnowOnGround']
">
365 <xsl:param name="date
" />
368 <xsl:when test="not(text())
">
369 <xsl:text>null</xsl:text>
371 <xsl:when test="contains(text(), '#')
">
372 <xsl:message>WARNING: <xsl:value-of select="$date
" />: Discard extremeSnowOnGround containing "#"
</xsl:message>
373 <xsl:text>null
</xsl:text>
375 <xsl:when test=
"@quality = '†'">
376 <xsl:message>WARNING:
<xsl:value-of select=
"$date" />: Insert not reviewed extremeSnowOnGround value
</xsl:message>
377 <xsl:value-of select=
"text()" />
380 <xsl:value-of select=
"text()" />
385 <xsl:template match=
"pop">
386 <xsl:param name=
"date" />
389 <xsl:when test=
"not(text())">
390 <xsl:text>null
</xsl:text>
392 <xsl:when test=
"@quality = '†'">
393 <xsl:message terminate=
"yes">pop value not reviewed
</xsl:message>
396 <xsl:value-of select=
"text()" />
402 <xsl:template name=
"camel-case">
403 <xsl:param name=
"text" select=
"."/>
404 <xsl:variable name=
"uppercase">ABCDEFGHIJKLMNOPQRSTUVWXYZ
</xsl:variable>
405 <xsl:variable name=
"lowercase">abcdefghijklmnopqrstuvwxyz
</xsl:variable>
406 <xsl:variable name=
"word" select=
"substring-before(concat($text, ' '), ' ')" />
408 <xsl:value-of select=
"translate(substring($word, 1, 1), $lowercase, $uppercase)" />
409 <xsl:value-of select=
"translate(substring($word, 2), $uppercase, $lowercase)" />
411 <xsl:if test=
"contains($text, ' ')">
412 <xsl:text> </xsl:text>
413 <xsl:call-template name=
"camel-case">
414 <xsl:with-param name=
"text" select=
"substring-after($text, ' ')"/>