XSLT如果元素的两个值匹配则合并单元格?

时间:2016-04-05 09:57:19

标签: xml xslt xhtml

我正在尝试用XML和XSLT文件创建一个XHTML。

我想测试两个或多个XML元素的值是否与表中的其他元素重合,在这种情况下,我希望这些单元格在结果XHTML文件中合并。

为简单起见,我将使用一个简单的w3schools示例。 (更多人应该在stackoverflow上执行此操作)。

这是XML:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
</cd>
<cd>
    <title>Empire Burlesque</title>
    <artist>Bonnie Tyler</artist>
</cd>
<cd>
    <title>Empire Burlesque</title>
    <artist>Mr G</artist>
</cd>
<cd>
    <title>Greatest Hits</title>
    <artist>Dolly Parton</artist>
</cd>
</catalog>

这是XSLT:

<?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>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
  <th>Title</th>
  <th>Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
  <xsl:choose>
  <xsl:when test="count(title) %gr 2">
     <td rowspan="2"><xsl:value-of select="title"/></td>
  </xsl:when>
  <xsl:otherwise>
     <td><xsl:value-of select="title"/></td>
  </xsl:otherwise>
  </xsl:choose>
  <td><xsl:value-of select="artist"/></td>
  </tr>
  </xsl:for-each>
  </table>
  </body>
  </html>
  </xsl:template>
  </xsl:stylesheet>

XSLT中的两个错误元素是:TEST和ROWSPAN。

  1. 如何测试标题是否有多个实例? (在这种情况下,Empire Burlesque)

  2. 如何告诉程序在这种情况下合并这两个单元格(因此输出是一个单元格,显示Empire Burlesque)和rowspan 3。

  3. 注意:请不要告诉我做test ='Empire Burlesque'。如果我将它们添加到哪里,我希望它能用于其他重复实例。谢谢。

1 个答案:

答案 0 :(得分:0)

我不会告诉你做测试=&#39; Empire Burlesque&#39;但我会告诉您阅读XSLT 1.0中名为Muenchian Grouping的技术,该技术允许您按cd

分组title元素

在您的情况下,您首先定义一个按标题查找cds的键

<xsl:key name="cds" match="cd" use="title" />

然后,要获得不同的标题(或者更确切地说,为了获得每个不同标题的第一次出现的cd元素),您将使用此表达式

<xsl:for-each select="catalog/cd[generate-id() = generate-id(key('cds', title)[1])]">

在这个循环中,您可以使用该键将所有具有匹配标题的cds分组。例如,要查看是否需要行数,请执行此操作

<xsl:if test="count(key('cds', title)) > 1">

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

<xsl:key name="cds" match="cd" use="title" />

<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
  <th>Title</th>
  <th>Artist</th>
</tr>
<xsl:for-each select="catalog/cd[generate-id() = generate-id(key('cds', title)[1])]">
<tr>
  <td>
      <xsl:if test="key('cds', title)[2]">
          <xsl:attribute name="rowspan">
              <xsl:value-of select="count(key('cds', title))" />
          </xsl:attribute>
      </xsl:if>
      <xsl:value-of select="title"/>
  </td>
  <td><xsl:value-of select="artist"/></td>
</tr>
<xsl:for-each select="key('cds', title)[position() > 1]">
<tr>
    <td>
      <xsl:value-of select="artist"/>
    </td>
</tr>    
</xsl:for-each>
  </xsl:for-each>
  </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>