From b7d25db04974e7fb6763a280fc9c52d5a80bd0a4 Mon Sep 17 00:00:00 2001 From: Pierre Choffet <peuc@wanadoo.fr> Date: Tue, 25 May 2021 18:12:31 -0400 Subject: [PATCH] Rewrite almanach merge logic Partial input/merge files use was flawed: missing days were triggering errors. Some traps were added to make sure we won't generate files with unexpected corner cases. --- eccc_merger_almanach.xslt | 180 ++++++++++++++++++++++++++++++-------- 1 file changed, 144 insertions(+), 36 deletions(-) diff --git a/eccc_merger_almanach.xslt b/eccc_merger_almanach.xslt index 38db64e..0f70b05 100644 --- a/eccc_merger_almanach.xslt +++ b/eccc_merger_almanach.xslt @@ -91,17 +91,29 @@ <xsl:variable name="merge-extreme-max" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/temperature[@class = 'extremeMax']" /> <xsl:choose> - <xsl:when test="$input-extreme-max and (not($merge-extreme-max) or $input-extreme-max/text() >= $merge-extreme-max/text())"> + <!-- Both nodes values are numeric and input value is greater or equal than merge + or Input exists but merge doesn't or is not numeric + --> + <xsl:when test="(string(number($input-extreme-max)) != 'NaN' and string(number($merge-extreme-max) != 'NaN') and $input-extreme-max >= $merge-extreme-max) or ($input-extreme-max and (string(number($merge-extreme-max)) = 'NaN'))"> <xsl:copy> <xsl:apply-templates select="$input-extreme-max/@*" /> <xsl:apply-templates select="$input-extreme-max/node()" /> </xsl:copy> </xsl:when> - <xsl:otherwise> + <!-- Both nodes values are numeric and input value is lesser than merge + or Input doesn't exist or is not numeric but merge does + --> + <xsl:when test="(string(number($input-extreme-max)) != 'NaN' and string(number($merge-extreme-max) != 'NaN') and $input-extreme-max < $merge-extreme-max) or ((string(number($input-extreme-max)) = 'NaN') and $merge-extreme-max)"> <xsl:copy> <xsl:apply-templates select="$merge-extreme-max/@*" /> <xsl:apply-templates select="$merge-extreme-max/node()" /> </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:value-of select="concat($month, '-', $day, ' - extremeMax ', number($input-extreme-max), ' ', number($merge-extreme-max))" /> + </xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -113,17 +125,29 @@ <xsl:variable name="merge-extreme-min" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/temperature[@class = 'extremeMin']" /> <xsl:choose> - <xsl:when test="$input-extreme-min and (not($merge-extreme-min) or $input-extreme-min/text() <= merge-extreme-min/text())"> + <!-- Both nodes values are numeric and input value is lesser or equal than merge + or Input exists but merge doesn't or is not numeric + --> + <xsl:when test="(string(number($input-extreme-min)) != 'NaN' and string(number($merge-extreme-min) != 'NaN') and $input-extreme-min <= $merge-extreme-min) or ($input-extreme-min and (string(number($merge-extreme-min)) = 'NaN'))"> <xsl:copy> <xsl:apply-templates select="$input-extreme-min/@*" /> <xsl:apply-templates select="$input-extreme-min/node()" /> </xsl:copy> </xsl:when> - <xsl:otherwise> + <!-- Both nodes values are numeric and input value is greater than merge + or Input doesn't exist or is not numeric but merge does + --> + <xsl:when test="(string(number($input-extreme-min)) != 'NaN' and string(number($merge-extreme-min) != 'NaN') and $input-extreme-min > $merge-extreme-min) or ((string(number($input-extreme-min)) = 'NaN') and $merge-extreme-min)"> <xsl:copy> <xsl:apply-templates select="$merge-extreme-min/@*" /> <xsl:apply-templates select="$merge-extreme-min/node()" /> </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:value-of select="concat($month, '-', $day, ' - extremeMin ', number($input-extreme-min), ' ', number($merge-extreme-min))" /> + </xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -135,17 +159,29 @@ <xsl:variable name="merge-normal-max" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/temperature[@class = 'normalMax']" /> <xsl:choose> - <xsl:when test="$input-normal-max and (not($merge-normal-max) or $input-normal-max/text() >= $merge-normal-max/text())"> + <!-- Both nodes values are numeric and input value is greater or equal than merge + or Input exists but merge doesn't or is not numeric + --> + <xsl:when test="(string(number($input-normal-max)) != 'NaN' and string(number($merge-normal-max) != 'NaN') and $input-normal-max >= $merge-normal-max) or ($input-normal-max and (string(number($merge-normal-max)) = 'NaN'))"> <xsl:copy> <xsl:apply-templates select="$input-normal-max/@*" /> <xsl:apply-templates select="$input-normal-max/node()" /> </xsl:copy> </xsl:when> - <xsl:otherwise> + <!-- Both nodes values are numeric and input value is lesser than merge + or Input doesn't exist or is not numeric but merge does + --> + <xsl:when test="(string(number($input-normal-max)) != 'NaN' and string(number($merge-normal-max) != 'NaN') and $input-normal-max < $merge-normal-max) or ((string(number($input-normal-max)) = 'NaN') and $merge-normal-max)"> <xsl:copy> <xsl:apply-templates select="$merge-normal-max/@*" /> <xsl:apply-templates select="$merge-normal-max/node()" /> </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:value-of select="concat($month, '-', $day, ' - normalMax ', number($input-normal-max), ' ', number($merge-normal-max))" /> + </xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -157,17 +193,29 @@ <xsl:variable name="merge-normal-min" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/temperature[@class = 'normalMin']" /> <xsl:choose> - <xsl:when test="$input-normal-min and (not($merge-normal-min) or $input-normal-min/text() <= $merge-normal-min/text())"> + <!-- Both nodes values are numeric and input value is lesser or equal than merge + or Input exists but merge doesn't or is not numeric + --> + <xsl:when test="(string(number($input-normal-min)) != 'NaN' and string(number($merge-normal-min) != 'NaN') and $input-normal-min <= $merge-normal-min) or ($input-normal-min and (string(number($merge-normal-min)) = 'NaN'))"> <xsl:copy> <xsl:apply-templates select="$input-normal-min/@*" /> <xsl:apply-templates select="$input-normal-min/node()" /> </xsl:copy> </xsl:when> - <xsl:otherwise> + <!-- Both nodes values are numeric and input value is greater than merge + or Input doesn't exist or is not numeric but merge does + --> + <xsl:when test="(string(number($input-normal-min)) != 'NaN' and string(number($merge-normal-min) != 'NaN') and $input-normal-min > $merge-normal-min) or ((string(number($input-normal-min)) = 'NaN') and $merge-normal-min)"> <xsl:copy> <xsl:apply-templates select="$merge-normal-min/@*" /> <xsl:apply-templates select="$merge-normal-min/node()" /> </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:value-of select="concat($month, '-', $day, ' - normalMin ', number($input-normal-min), ' ', number($merge-normal-min))" /> + </xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -179,37 +227,43 @@ <xsl:variable name="merge-normal-mean" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/temperature[@class = 'normalMean']" /> <xsl:choose> - <xsl:when test="$input-normal-mean and $input-normal-mean/text() != '' and $merge-normal-mean and $merge-normal-mean/text() != ''"> + <!-- Node exists and are not empty on both sides --> + <xsl:when test="$input-normal-mean and $input-normal-mean != '' and $merge-normal-mean and $merge-normal-mean/text() != ''"> <xsl:copy> <xsl:apply-templates select="$input-normal-mean/@*" /> <xsl:attribute name="values-count"><xsl:value-of select="$input-normal-mean/@values-count + 1" /></xsl:attribute> <xsl:value-of select="format-number(number($input-normal-mean/text() * $input-normal-mean/@values-count + $merge-normal-mean/text()) div number($input-normal-mean/@values-count + 1), '0.0')" /> </xsl:copy> </xsl:when> - <xsl:when test="$input-normal-mean != '' and (not($merge-normal-mean) or $merge-normal-mean = '')"> + <!-- Node exists but are empty on both sides --> + <xsl:when test="$input-normal-mean = '' and $merge-normal-mean = ''"> <xsl:copy> <xsl:apply-templates select="$input-normal-mean/@*" /> <xsl:apply-templates select="$input-normal-mean/node()" /> </xsl:copy> </xsl:when> - <xsl:when test="(not($input-normal-mean) or $input-normal-mean = '') and $merge-normal-mean and $merge-normal-mean != ''"> + <!-- Node exists in input but not-or-empty in merge --> + <xsl:when test="$input-normal-mean and (not($merge-normal-mean) or $merge-normal-mean = '')"> <xsl:copy> - <xsl:apply-templates select="$merge-normal-mean/@*" /> - <xsl:attribute name="values-count">1</xsl:attribute> - <xsl:apply-templates select="$merge-normal-mean/node()" /> + <xsl:apply-templates select="$input-normal-mean/@*" /> + <xsl:apply-templates select="$input-normal-mean/node()" /> </xsl:copy> </xsl:when> - <xsl:when test="$input-normal-mean = '' and $merge-normal-mean = ''"> + <!-- Node doesn't exist or is empty in input and exists in merge --> + <xsl:when test="(not($input-normal-mean) or $input-normal-mean = '') and $merge-normal-mean"> <xsl:copy> - <xsl:apply-templates select="$input-normal-mean/@*" /> - <xsl:apply-templates select="$input-normal-mean/node()" /> + <xsl:apply-templates select="$merge-normal-mean/@*" /> + <xsl:if test="$merge-normal-mean != ''"> + <xsl:attribute name="values-count">1</xsl:attribute> + <xsl:apply-templates select="$merge-normal-mean/node()" /> + </xsl:if> </xsl:copy> </xsl:when> <xsl:otherwise> <xsl:message terminate="no"> <xsl:value-of select="concat($month, '-', $day, ' - normalMean: ', $input-normal-mean, ' ', $merge-normal-mean)" /> </xsl:message> - <xsl:message terminate="yes">Trapping case not supposed to happend.</xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -221,17 +275,29 @@ <xsl:variable name="merge-precipitation-rainfall" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/precipitation[@class = 'extremeRainfall']" /> <xsl:choose> - <xsl:when test="$input-precipitation-rainfall and (not($merge-precipitation-rainfall) or $input-precipitation-rainfall/text() >= $merge-precipitation-rainfall/text())"> + <!-- Both nodes values are numeric and input value is greater or equal than merge + or Input exists but merge doesn't or is not numeric + --> + <xsl:when test="(string(number($input-precipitation-rainfall)) != 'NaN' and string(number($merge-precipitation-rainfall) != 'NaN') and $input-precipitation-rainfall >= $merge-precipitation-rainfall) or ($input-precipitation-rainfall and (string(number($merge-precipitation-rainfall)) = 'NaN'))"> <xsl:copy> <xsl:apply-templates select="$input-precipitation-rainfall/@*" /> <xsl:apply-templates select="$input-precipitation-rainfall/node()" /> </xsl:copy> </xsl:when> - <xsl:otherwise> + <!-- Both nodes values are numeric and input value is lesser than merge + or Input doesn't exist or is not numeric but merge does + --> + <xsl:when test="(string(number($input-precipitation-rainfall)) != 'NaN' and string(number($merge-precipitation-rainfall) != 'NaN') and $input-precipitation-rainfall < $merge-precipitation-rainfall) or ((string(number($input-precipitation-rainfall)) = 'NaN') and $merge-precipitation-rainfall)"> <xsl:copy> <xsl:apply-templates select="$merge-precipitation-rainfall/@*" /> <xsl:apply-templates select="$merge-precipitation-rainfall/node()" /> </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:value-of select="concat($month, '-', $day, ' - extremeRainfall ', number($input-precipitation-rainfall), ' ', number($merge-precipitation-rainfall))" /> + </xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -243,17 +309,29 @@ <xsl:variable name="merge-precipitation-snowfall" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/precipitation[@class = 'extremeSnowfall']" /> <xsl:choose> - <xsl:when test="$input-precipitation-snowfall and (not($merge-precipitation-snowfall) or $input-precipitation-snowfall/text() >= $merge-precipitation-snowfall/text())"> + <!-- Both nodes values are numeric and input value is greater or equal than merge + or Input exists but merge doesn't or is not numeric + --> + <xsl:when test="(string(number($input-precipitation-snowfall)) != 'NaN' and string(number($merge-precipitation-snowfall) != 'NaN') and $input-precipitation-snowfall >= $merge-precipitation-snowfall) or ($input-precipitation-snowfall and (string(number($merge-precipitation-snowfall)) = 'NaN'))"> <xsl:copy> <xsl:apply-templates select="$input-precipitation-snowfall/@*" /> <xsl:apply-templates select="$input-precipitation-snowfall/node()" /> </xsl:copy> </xsl:when> - <xsl:otherwise> + <!-- Both nodes values are numeric and input value is lesser than merge + or Input doesn't exist or is not numeric but merge does + --> + <xsl:when test="(string(number($input-precipitation-snowfall)) != 'NaN' and string(number($merge-precipitation-snowfall) != 'NaN') and $input-precipitation-snowfall < $merge-precipitation-snowfall) or ((string(number($input-precipitation-snowfall)) = 'NaN') and $merge-precipitation-snowfall)"> <xsl:copy> <xsl:apply-templates select="$merge-precipitation-snowfall/@*" /> <xsl:apply-templates select="$merge-precipitation-snowfall/node()" /> </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:value-of select="concat($month, '-', $day, ' - extremeSnowfall ', number($input-precipitation-snowfall), ' ', number($merge-precipitation-snowfall))" /> + </xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -265,17 +343,29 @@ <xsl:variable name="merge-precipitation-extreme" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/precipitation[@class = 'extremePrecipitation']" /> <xsl:choose> - <xsl:when test="$input-precipitation-extreme and (not($merge-precipitation-extreme) or $input-precipitation-extreme/text() >= $merge-precipitation-extreme/text())"> + <!-- Both nodes values are numeric and input value is greater or equal than merge + or Input exists but merge doesn't or is not numeric + --> + <xsl:when test="(string(number($input-precipitation-extreme)) != 'NaN' and string(number($merge-precipitation-extreme) != 'NaN') and $input-precipitation-extreme >= $merge-precipitation-extreme) or ($input-precipitation-extreme and (string(number($merge-precipitation-extreme)) = 'NaN'))"> <xsl:copy> <xsl:apply-templates select="$input-precipitation-extreme/@*" /> <xsl:apply-templates select="$input-precipitation-extreme/node()" /> </xsl:copy> </xsl:when> - <xsl:otherwise> + <!-- Both nodes values are numeric and input value is lesser than merge + or Input doesn't exist or is not numeric but merge does + --> + <xsl:when test="(string(number($input-precipitation-extreme)) != 'NaN' and string(number($merge-precipitation-extreme) != 'NaN') and $input-precipitation-extreme < $merge-precipitation-extreme) or ((string(number($input-precipitation-extreme)) = 'NaN') and $merge-precipitation-extreme)"> <xsl:copy> <xsl:apply-templates select="$merge-precipitation-extreme/@*" /> <xsl:apply-templates select="$merge-precipitation-extreme/node()" /> </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:value-of select="concat($month, '-', $day, ' - extremePrecipitation ', number($input-precipitation-extreme), ' ', number($merge-precipitation-extreme))" /> + </xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -287,17 +377,29 @@ <xsl:variable name="merge-precipitation-snow-ground" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/precipitation[@class = 'extremeSnowOnGround']" /> <xsl:choose> - <xsl:when test="$input-precipitation-snow-ground and (not($merge-precipitation-snow-ground) or $input-precipitation-snow-ground/text() >= $merge-precipitation-snow-ground/text())"> + <!-- Both nodes values are numeric and input value is greater or equal than merge + or Input exists but merge doesn't or is not numeric + --> + <xsl:when test="(string(number($input-precipitation-snow-ground)) != 'NaN' and string(number($merge-precipitation-snow-ground) != 'NaN') and $input-precipitation-snow-ground >= $merge-precipitation-snow-ground) or ($input-precipitation-snow-ground and (string(number($merge-precipitation-snow-ground)) = 'NaN'))"> <xsl:copy> <xsl:apply-templates select="$input-precipitation-snow-ground/@*" /> <xsl:apply-templates select="$input-precipitation-snow-ground/node()" /> </xsl:copy> </xsl:when> - <xsl:otherwise> + <!-- Both nodes values are numeric and input value is lesser than merge + or Input doesn't exist or is not numeric but merge does + --> + <xsl:when test="(string(number($input-precipitation-snow-ground)) != 'NaN' and string(number($merge-precipitation-snow-ground) != 'NaN') and $input-precipitation-snow-ground < $merge-precipitation-snow-ground) or ((string(number($input-precipitation-snow-ground)) = 'NaN') and $merge-precipitation-snow-ground)"> <xsl:copy> <xsl:apply-templates select="$merge-precipitation-snow-ground/@*" /> <xsl:apply-templates select="$merge-precipitation-snow-ground/node()" /> </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:value-of select="concat($month, '-', $day, ' - extremeSnowOnGround ', number($input-precipitation-snow-ground), ' ', number($merge-precipitation-snow-ground))" /> + </xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -309,37 +411,43 @@ <xsl:variable name="merge-pop" select="$merge-doc/climatedata/month[@index = $month]/day[@index = $day]/pop" /> <xsl:choose> - <xsl:when test="$input-pop and $input-pop/text() != '' and $merge-pop and $merge-pop/text() != ''"> + <!-- Node exists and are not empty on both sides --> + <xsl:when test="$input-pop and $input-pop != '' and $merge-pop and $merge-pop/text() != ''"> <xsl:copy> <xsl:apply-templates select="$input-pop/@*" /> <xsl:attribute name="values-count"><xsl:value-of select="$input-pop/@values-count + 1" /></xsl:attribute> <xsl:value-of select="format-number(number($input-pop/text() * $input-pop/@values-count + $merge-pop/text()) div number($input-pop/@values-count + 1), '0.0')" /> </xsl:copy> </xsl:when> - <xsl:when test="$input-pop != '' and (not($merge-pop) or $merge-pop = '')"> + <!-- Node exists but are empty on both sides --> + <xsl:when test="$input-pop = '' and $merge-pop = ''"> <xsl:copy> <xsl:apply-templates select="$input-pop/@*" /> <xsl:apply-templates select="$input-pop/node()" /> </xsl:copy> </xsl:when> - <xsl:when test="(not($input-pop) or $input-pop = '') and $merge-pop and $merge-pop/text() != ''"> + <!-- Node exists in input but not-or-empty in merge --> + <xsl:when test="$input-pop and (not($merge-pop) or $merge-pop = '')"> <xsl:copy> - <xsl:apply-templates select="$merge-pop/@*" /> - <xsl:attribute name="values-count">1</xsl:attribute> - <xsl:apply-templates select="$merge-pop/node()" /> + <xsl:apply-templates select="$input-pop/@*" /> + <xsl:apply-templates select="$input-pop/node()" /> </xsl:copy> </xsl:when> - <xsl:when test="(not($input-pop) or $input-pop = '') and (not($merge-pop) or $merge-pop = '')"> + <!-- Node doesn't exist or is empty in input and exists in merge --> + <xsl:when test="(not($input-pop) or $input-pop = '') and $merge-pop"> <xsl:copy> - <xsl:apply-templates select="$input-pop/@*" /> - <xsl:apply-templates select="$input-pop/node()" /> + <xsl:apply-templates select="$merge-pop/@*" /> + <xsl:if test="$merge-pop != ''"> + <xsl:attribute name="values-count">1</xsl:attribute> + <xsl:apply-templates select="$merge-pop/node()" /> + </xsl:if> </xsl:copy> </xsl:when> <xsl:otherwise> <xsl:message terminate="no"> <xsl:value-of select="concat($month, '-', $day, ' - pop: ', $input-pop, ' ', $merge-pop)" /> </xsl:message> - <xsl:message terminate="yes">Trapping case not supposed to happend.</xsl:message> + <xsl:message terminate="yes">Trapping case not supposed to happen.</xsl:message> </xsl:otherwise> </xsl:choose> </xsl:template> -- 2.42.0