如果行具有相同的值,则合并 XSLT 行

4
我对XML和XSLT文档还比较陌生。我创建了一个XML文档,其中包含跨越几个月的天气数据记录。我想使用XSLT文档将每个表行中同一月份的记录分组,并在跨越同一月份所有行的列上打印它们的月份(如果月份=2,则打印Feb)。我是否可以使用if-else语句来输出相应的月份并如何合并具有相同月份值的表行?
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>

这是我目前的XSL文件:
<?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>

我试图实现的输出结果如下所示:

图像


1
请在您的问题中添加预期输出作为代码 - michael.hor257k
你必须使用XSLT 1.0吗?还是2.0或更高版本对你来说也是一个选择?xsl:for-each-group会让事情变得更容易,但在1.0中不可用。 - Mads Hansen
嗨@MadsHansen,我能使用XSLT 2.0,但我不确定如何实现xsl:for-each-group并按其月份值对行进行排序。 - user14512303
1个回答

1
为此,我将使用 xsl:for-each-group 指定 grouping-key month 值:<xsl:for-each-group select =“weather”group-by =“month”>

在循环内,迭代 current-group()以处理每个分组的 weather 元素以生成列表:<xsl:for-each select =“current-group()”>

您可以从分组的 weather 元素集中获得 min() max()值:max(current-group()/ highest)

使用月份编号作为位置,您可以使用谓词从一系列月份缩写中进行选择。由于有前导零,因此请使用number()进行转换,即将02转换为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>

非常感谢@MadsHansen,我现在能够理解xsl:for-each-group的工作原理了,但是我无法查看由您的XSL代码格式化的XML文件内容。我正在使用与我在问题中提到的相同的XML文件。我需要在XML文件中声明一些内容才能使它正常工作吗? - user14512303

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接