如何在xsl文件样式表中合并单元格?

时间:2016-03-30 14:59:52

标签: xml xslt xhtml

我被告知要合并出现在同一地点的公交车站的所有常用名称,例如Aberdeen有三个常用站点,但它们位于不同的单元格中。我如何将这些结合起来,以便所有常见的句点出现在我的XSL样式表中的一个地点Aberdeen下?

下面是我的样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>BusStops</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Locality</th>
        <th>BusStop</th>
        <th> Co-ordinates </th>
      </tr>
      <xsl:for-each select="BusStops/BusStopDetails">
      <xsl:sort select="LocalityName"/>     
      <tr>  
        <td> <xsl:value-of select="LocalityName"/> (<xsl:value-of select="ParentLocalityName"/>) </td>
        <td><xsl:value-of select="CommonName"/></td>
        <td>
             <a href="https://maps.google.com/maps?ll={Latitude},{Longitude}&amp;q={Latitude},{Longitude}&amp;hl=en&amp;t=m&amp;z=14">
             (<xsl:value-of select="Latitude"/>) , (<xsl:value-of select="Longitude"/>)
            </a>
        </td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

这是我的XML示例:

<BusStopDetails>
    <AtcoCode>639070021
    </AtcoCode> 
    <CommonName>Union Square Bus Station
    </CommonName>
    <LocalityName>Aberdeen
    </LocalityName>
    <ParentLocalityName/>
    <Latitude>57.1445763077
    </Latitude>
    <Longitude>-2.0963111958
    </Longitude>
</BusStopDetails>

<BusStopDetails>
    <AtcoCode>639080008
    </AtcoCode>
    <CommonName>Aberdeen Railway Station
    </CommonName>
    <LocalityName>Aberdeen
    </LocalityName>
    <ParentLocalityName/>
    <Latitude>57.1437934462
    </Latitude>
    <Longitude>-2.0980112638
    </Longitude>
</BusStopDetails>

-<BusStopDetails>
    <AtcoCode>9300ABA
    </AtcoCode>
    <CommonName>Aberdeen Ferry Terminal
    </CommonName>
    <LocalityName>Aberdeen
    </LocalityName>
    <ParentLocalityName/>
    <Latitude>57.1447953603
    </Latitude>
    <Longitude>-2.0917010936
    </Longitude>
</BusStopDetails>

3 个答案:

答案 0 :(得分:1)

这是另一个也使用xsl:key ...

的例子

XML输入(添加了另一个BusStopDetails以获得更好的示例)

<BusStops>
    <BusStopDetails>
        <AtcoCode>639070021</AtcoCode>
        <CommonName>Some common name</CommonName>
        <LocalityName>Stackoverflow</LocalityName>
        <ParentLocalityName>Some Parent Loc</ParentLocalityName>
        <Latitude>57.1445763077</Latitude>
        <Longitude>-2.0963111958</Longitude>
    </BusStopDetails>
    <BusStopDetails>
        <AtcoCode>639070021</AtcoCode>
        <CommonName>Union Square Bus Station</CommonName>
        <LocalityName>Aberdeen</LocalityName>
        <ParentLocalityName/>
        <Latitude>57.1445763077</Latitude>
        <Longitude>-2.0963111958</Longitude>
    </BusStopDetails>
    <BusStopDetails>
        <AtcoCode>639080008</AtcoCode>
        <CommonName>Aberdeen Railway Station</CommonName>
        <LocalityName>Aberdeen
        </LocalityName>
        <ParentLocalityName/>
        <Latitude>57.1437934462</Latitude>
        <Longitude>-2.0980112638</Longitude>
    </BusStopDetails>
    <BusStopDetails>
        <AtcoCode>9300ABA</AtcoCode>
        <CommonName>Aberdeen Ferry Terminal</CommonName>
        <LocalityName>Aberdeen    </LocalityName>
        <ParentLocalityName/>
        <Latitude>57.1447953603</Latitude>
        <Longitude>-2.0917010936</Longitude>
    </BusStopDetails>
</BusStops>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="detailsByLocality" match="BusStopDetails" use="normalize-space(LocalityName)"/>

  <xsl:template match="/BusStops">
    <html>
      <body>
        <h2>BusStops</h2>
        <table border="1">
          <tr bgcolor="#9acd32">
            <th>Locality</th>
            <th>BusStop</th>
            <th>Co-ordinates</th>
          </tr>
          <xsl:for-each select="BusStopDetails[count(.|key('detailsByLocality',normalize-space(LocalityName))[1])=1]">
            <xsl:sort select="LocalityName"/>
            <tr>
              <td rowspan="{count(key('detailsByLocality',normalize-space(LocalityName))) + 1}">
                <xsl:value-of select="normalize-space(LocalityName)"/>
                <xsl:apply-templates select="ParentLocalityName"/>
              </td>
            </tr>
            <xsl:apply-templates select="key('detailsByLocality',normalize-space(LocalityName))"/>
          </xsl:for-each>          
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="BusStopDetails">
    <tr>
      <td><xsl:value-of select="normalize-space(CommonName)"/></td>
      <td>
        <a
          href="https://maps.google.com/maps?ll={Latitude},{Longitude}&amp;q={Latitude},{Longitude}&amp;hl=en&amp;t=m&amp;z=14">
          <xsl:value-of select="concat('(',Latitude,' , ',Longitude,')')"/>
        </a>
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="ParentLocalityName[string()]">
    <xsl:value-of select="concat(' (',normalize-space(),')')"/>
  </xsl:template>

</xsl:stylesheet>

<强>输出

<html>
   <body>
      <h2>BusStops</h2>
      <table border="1">
         <tr bgcolor="#9acd32">
            <th>Locality</th>
            <th>BusStop</th>
            <th>Co-ordinates</th>
         </tr>
         <tr>
            <td rowspan="4">Aberdeen</td>
         </tr>
         <tr>
            <td>Union Square Bus Station</td>
            <td><a href="https://maps.google.com/maps?ll=57.1445763077,-2.0963111958&amp;q=57.1445763077,-2.0963111958&amp;hl=en&amp;t=m&amp;z=14">(57.1445763077 , -2.0963111958)</a></td>
         </tr>
         <tr>
            <td>Aberdeen Railway Station</td>
            <td><a href="https://maps.google.com/maps?ll=57.1437934462,-2.0980112638&amp;q=57.1437934462,-2.0980112638&amp;hl=en&amp;t=m&amp;z=14">(57.1437934462 , -2.0980112638)</a></td>
         </tr>
         <tr>
            <td>Aberdeen Ferry Terminal</td>
            <td><a href="https://maps.google.com/maps?ll=57.1447953603,-2.0917010936&amp;q=57.1447953603,-2.0917010936&amp;hl=en&amp;t=m&amp;z=14">(57.1447953603 , -2.0917010936)</a></td>
         </tr>
         <tr>
            <td rowspan="2">Stackoverflow (Some Parent Loc)</td>
         </tr>
         <tr>
            <td>Some common name</td>
            <td><a href="https://maps.google.com/maps?ll=57.1445763077,-2.0963111958&amp;q=57.1445763077,-2.0963111958&amp;hl=en&amp;t=m&amp;z=14">(57.1445763077 , -2.0963111958)</a></td>
         </tr>
      </table>
   </body>
</html>

Working Example

答案 1 :(得分:0)

这可以通过以下样式表来实现。我还没有修改你的格式,我只是调整了模板的布局。您可能应该使用/root或类似的内容替换第一个模板中的BusStops。我无法详细说明这一点,因为您没有提供完整的XML文件。但这对你来说是微不足道的。我还将已排序的for-each替换为已排序的apply-templates。它运作良好。如果您不希望结果按CommonName排序,而是按LocalityName排序,请将其替换。或者添加第二个图层,按CommonName排序,然后按LocalityName排序。这个解决方案应该具有指导意义。

XML文件

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="a.xslt"?>
<root>
<BusStopDetails>
    <AtcoCode>639070021
    </AtcoCode> 
    <CommonName>Union Square Bus Station
    </CommonName>
    <LocalityName>Aberdeen
    </LocalityName>
    <ParentLocalityName/>
    <Latitude>57.1445763077
    </Latitude>
    <Longitude>-2.0963111958
    </Longitude>
</BusStopDetails>

<BusStopDetails>
    <AtcoCode>639080008
    </AtcoCode>
    <CommonName>Aberdeen Railway Station
    </CommonName>
    <LocalityName>Aberdeen
    </LocalityName>
    <ParentLocalityName/>
    <Latitude>57.1437934462
    </Latitude>
    <Longitude>-2.0980112638
    </Longitude>
</BusStopDetails>

-<BusStopDetails>
    <AtcoCode>9300ABA
    </AtcoCode>
    <CommonName>Aberdeen Ferry Terminal
    </CommonName>
    <LocalityName>Aberdeen
    </LocalityName>
    <ParentLocalityName/>
    <Latitude>57.1447953603
    </Latitude>
    <Longitude>-2.0917010936
    </Longitude>
</BusStopDetails>
</root>

XSLT文件

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/root">
    <html>
      <body>
        <h2>BusStops</h2>
        <table border="1">
          <tr bgcolor="#9acd32">
            <th>Locality</th>
            <th>BusStop</th>
            <th>Coordinates </th>
          </tr>
          <xsl:apply-templates select="BusStopDetails">
            <xsl:sort select="LocalityName" order="ascending" />
            <xsl:sort select="CommonName" order="ascending" />
          </xsl:apply-templates>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="BusStopDetails">   <!-- in your setup you may use 'BusStops/BusStopDetails' --> 
    <tr>  
      <td> <xsl:value-of select="LocalityName"/> (<xsl:value-of select="ParentLocalityName"/>) </td>
      <td><xsl:value-of select="CommonName"/></td>
      <td>
        <a href="https://maps.google.com/maps?ll={Latitude},{Longitude}&amp;q={Latitude},{Longitude}&amp;hl=en&amp;t=m&amp;z=14">
          (<xsl:value-of select="Latitude"/>) , (<xsl:value-of select="Longitude"/>)
        </a>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

这是一个简单的XSL 1.0解决方案/想法,使用for-each和key。 1.生成密钥:

<xsl:key  name="kLocalityName" match="BusStopDetails" use="LocalityName"/>

2遍历小组:

   <xsl:for-each select="BusStopDetails[generate-id() = 
                                generate-id(key('kLocalityName', LocalityName)[1])]"  >
  1. 遍历每个组成员:

    <xsl:for-each select="key('kLocalityName', $this)" >
    
  2. 更新
    试试这个(没有html输出 - 因为我不知道它应该如何锁定)

        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:output method="xml" indent="yes" />
            <xsl:key  name="kLocalityName" match="BusStopDetails" use="LocalityName"/>
            <xsl:template match="/*">
                            <!--for-each select="BusStops/BusStopDetails" group >-->
                            <xsl:for-each select="BusStopDetails[generate-id() = 
                                                                                generate-id(key('kLocalityName', LocalityName)[1])]"  >
    
                                <xsl:sort select="LocalityName"/>
                                <BusStopGroup>
                                    <gname>
                                        <xsl:value-of select="LocalityName"/>
                                </gname>
                                    <xsl:variable name="this" select="LocalityName" />
                                    <xsl:for-each select="key('kLocalityName', $this)" >
                                        <BusStopDetails>
                                             <xsl:value-of select="CommonName"/>
                                        </BusStopDetails>
    
                                    </xsl:for-each>
                                </BusStopGroup>
                            </xsl:for-each>
            </xsl:template>
        </xsl:stylesheet>
    

    将生成:

    <BusStopGroup>
        <gname>Aberdeen</gname>
        <BusStopDetails>Union Square Bus Station</BusStopDetails>
        <BusStopDetails>Aberdeen Railway Station</BusStopDetails>
        <BusStopDetails>Aberdeen Ferry Terminal</BusStopDetails>
    </BusStopGroup>
    

    现在使用html更新2:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" indent="yes" />
        <xsl:key  name="kLocalityName" match="BusStopDetails" use="LocalityName"/>
        <xsl:template match="/*">
          <html>
              <body>
                <h2>BusStops</h2>
                <table border="1">
                  <tr bgcolor="#9acd32">
                    <th>Locality</th>
                    <th>BusStop</th>
                    <th> Co-ordinates </th>
                  </tr>
                        <!--for-each select="BusStops/BusStopDetails" group >-->
                        <xsl:for-each select="BusStopDetails[generate-id() = 
                                                                            generate-id(key('kLocalityName', LocalityName)[1])]"  >
    
                            <xsl:sort select="LocalityName"/>
                                <xsl:variable name="this" select="LocalityName" />
                                <xsl:for-each select="key('kLocalityName', $this)" >
                                  <tr> 
                                    <xsl:if test="position()=1">
                                      <td rowspan="{count(key('kLocalityName', $this))}"> 
                                        <xsl:value-of select="LocalityName"/> (<xsl:value-of select="ParentLocalityName"/>) </td>
                                    </xsl:if>                                      
                                    <td><xsl:value-of select="CommonName"/></td>
                                    <td>
                                         <a href="https://maps.google.com/maps?ll={Latitude},{Longitude}&amp;q={Latitude},{Longitude}&amp;hl=en&amp;t=m&amp;z=14">
                                         (<xsl:value-of select="Latitude"/>) , (<xsl:value-of select="Longitude"/>)
                                        </a>
                                    </td>
                                  </tr>
                                </xsl:for-each>
                        </xsl:for-each>
                </table>
            </body>
          </html>
        </xsl:template>
    </xsl:stylesheet>