Reputation:
I'm fairly new to XML and XSLT documents. I have created an XML document that has records of weather data which spans over a few months. I want to use an XSLT document to group together records of the same month within each table row and then print their months (if month = 2, Feb will be printed) on the column which spans across all the rows in the same month. Is there any way I can use if-else statements to print out the corresponding months and how do I merge the table rows if they have the same month value?
XML:
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="S3(1).xsl" ?>
<forecast xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="S3.xsd"
qTime="28/10/20 10:00 PM">
<weather yyyymmdd="20200430">
<year>2020</year>
<month>04</month>
<date>30</date>
<comment>Plenty of sunshine</comment>
<code>sunny</code>
<highest>32.6</highest>
<lowest>28.4</lowest>
</weather>
<weather yyyymmdd="20200218">
<year>2020</year>
<month>02</month>
<date>18</date>
<comment>Plenty of sunshine</comment>
<code>sunny</code>
<highest>34.6</highest>
<lowest>30.5</lowest>
</weather>
<weather yyyymmdd="20200710">
<year>2020</year>
<month>07</month>
<date>10</date>
<comment>Partly sunny</comment>
<code>partlySunny</code>
<highest>33.1</highest>
<lowest>29.2</lowest>
</weather>
<weather yyyymmdd="20200616">
<year>2020</year>
<month>06</month>
<date>16</date>
<comment>Considerable clouds</comment>
<code>cloudy</code>
<highest>30.5</highest>
<lowest>25.4</lowest>
</weather>
<weather yyyymmdd="20200612">
<year>2020</year>
<month>06</month>
<date>12</date>
<comment>Cloudy with a thunderstorm</comment>
<code>thunderstorm</code>
<highest>29.1</highest>
<lowest>23.2</lowest>
</weather>
<weather yyyymmdd="20200421">
<year>2020</year>
<month>04</month>
<date>21</date>
<comment>Plenty of sunshine</comment>
<code>sunny</code>
<highest>32.2</highest>
<lowest>29.8</lowest>
</weather>
<weather yyyymmdd="20200628">
<year>2020</year>
<month>06</month>
<date>28</date>
<comment>A morning shower, then rain</comment>
<code>rain</code>
<highest>30.2</highest>
<lowest>22.7</lowest>
</weather>
<weather yyyymmdd="20200502">
<year>2020</year>
<month>05</month>
<date>02</date>
<comment>Cloudy with a thunderstorm</comment>
<code>thunderstorm</code>
<highest>28.1</highest>
<lowest>26.9</lowest>
</weather>
<weather yyyymmdd="20200428">
<year>2020</year>
<month>04</month>
<date>28</date>
<comment>A morning shower</comment>
<code>rain</code>
<highest>28.8</highest>
<lowest>22.2</lowest>
</weather>
<weather yyyymmdd="20200410">
<year>2020</year>
<month>04</month>
<date>10</date>
<comment>Partly sunny</comment>
<code>partlySunny</code>
<highest>33.7</highest>
<lowest>29.3</lowest>
</weather>
<weather yyyymmdd="20200730">
<year>2020</year>
<month>07</month>
<date>30</date>
<comment>Plenty of sunshine</comment>
<code>sunny</code>
<highest>32.3</highest>
<lowest>28.4</lowest>
</weather>
<weather yyyymmdd="20200706">
<year>2020</year>
<month>07</month>
<date>06</date>
<comment>Plenty of sunshine</comment>
<code>sunny</code>
<highest>34.5</highest>
<lowest>30.6</lowest>
</weather>
</forecast>
This is my XSL file so far:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="forecast">
<h1>
<span> <xsl:value-of select="@qLocation"/></span>
<span>[<xsl:value-of select="@qTime"/>]</span>
</h1>
<table style="border:1px solid black;">
<tr>
<th>Date</th>
<th>Weather data</th>
<th>Highest</th>
<th>Lowest</th>
</tr>
<xsl:for-each select="weather">
<xsl:sort select="month" order="ascending"/>
<xsl:sort select="date" order="ascending"/>
<tr>
<td>
<span><xsl:value-of select="date"/>/</span>
<span><xsl:value-of select="month"/></span>
</td>
<td>
<li>
<xsl:value-of select="date"/>/
<xsl:value-of select="month"/>/
<xsl:value-of select="year"/>,
from
<xsl:value-of select="lowest"/>C
to
<xsl:value-of select="highest"/>C,
<xsl:value-of select="comment"/>
</li>
</td>
<td>
<xsl:value-of select="highest"/>C
<!-- <img src="img1.jpg"> -->
</td>
<td>
<xsl:value-of select="lowest"/>C
<!-- <img src="img2.jpg"> -->
</td>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The output I'm trying to achieve is something like this:
Upvotes: 4
Views: 735
Reputation: 66783
For this, I would use xsl:for-each-group
specifying the month
value for the grouping-key
: <xsl:for-each-group select="weather" group-by="month">
Inside of the loop, iterate over the current-group()
to process each of the grouped weather
elements to produce the list: <xsl:for-each select="current-group()">
You can obtain the min()
and max()
values from the grouped set of weather
elements: max(current-group()/highest)
Using the month number as a position, you can use a predicate to select from a sequence of month abbreviations. There was a leading zero, so use number()
to convert i.e. 02
to 2
: <xsl:sequence select="('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[number(current-grouping-key())]"/>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="forecast">
<h1>
<span> <xsl:value-of select="@qLocation"/></span>
<span>[<xsl:value-of select="@qTime"/>]</span>
</h1>
<table style="border:1px solid black;">
<tr>
<th>Date</th>
<th>Weather data</th>
<th>Highest</th>
<th>Lowest</th>
</tr>
<xsl:for-each-group select="weather" group-by="month">
<xsl:sort select="month" order="ascending"/>
<xsl:sort select="date" order="ascending"/>
<tr>
<td>
<span><xsl:value-of select="year"/>/</span>
<span><xsl:sequence select="('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[number(current-grouping-key())]"/></span>
</td>
<td>
<xsl:for-each select="current-group()">
<li>
<xsl:value-of select="date"/>/
<xsl:value-of select="month"/>/
<xsl:value-of select="year"/>,
from
<xsl:value-of select="lowest"/>C
to
<xsl:value-of select="highest"/>C,
<xsl:value-of select="comment"/>
</li>
</xsl:for-each>
</td>
<td>
<xsl:value-of select="max(current-group()/highest)"/>C
<!-- <img src="img1.jpg"> -->
</td>
<td>
<xsl:value-of select="min(current-group()/lowest)"/>C
<!-- <img src="img2.jpg"> -->
</td>
</tr>
</xsl:for-each-group>
</table>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1