XSL:在一个html标记中放置多个条目而不破坏标记结构

时间:2013-06-26 11:47:48

标签: xslt

我的XML源代码如下:

<query>
  <Rows>
    <Row ID="1" name="person1" title="p1package1" />
    <Row ID="2" name="person1" title="p1package2" />
    <Row ID="3" name="person2" title="p2package1" />
  </Rows>
</query>

我想用XSL创建一个输出:

<table>
  <tr>
    <td>person1</td>
    <td>p1package1, p1package2</td>
  </tr>
  <tr>
    <td>person2</td>
    <td>p2package1</td>
  </tr>
</table>

我尝试使用以下XSL-sylesheet,但在第一个之前打开似乎导致无效的结构,因此页面无法加载。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output version="1.0" indent="yes" encoding="UTF-8" method="xml" />  
    <xsl:template match='query'>
      <table>
        <xsl:for-each select="Rows/Row" >
          <xsl:if test="preceding-sibling::Row/@name != @name or position() = 1">
              <tr>
                <td><xsl:value-of select="@name" /></td>
                <td>
          </xsl:if>
          <xsl:value-of select="@title" />
          <xsl:if test="not(following-sibling::Row/@name = @name)">
                </td>
              </tr>
          </xsl:if>
        </xsl:for-each>
      </table>
    </xsl:template>
</xsl:stylesheet>

我怎么能接近这个?我知道XML的结构不是很好,但我对数据源没有影响。

2 个答案:

答案 0 :(得分:2)

为了完整性,这里是XSLT 2.0中的等价物

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output version="1.0" indent="yes" encoding="UTF-8" method="xml" />  
    <xsl:template match='query'>
      <table>
        <xsl:for-each-group select="Rows/Row" group-by="@name">
          <tr>
            <td><xsl:value-of select="@name"/></td>
            <td><xsl:value-of select="current-group()/@title" separator=", "/></td>
          </tr>
        </xsl:for-each-group>
      </table>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

在XSLT 1.0中对此类问题进行分组的标准方法是 Muenchian分组 - 您定义了一个按照您希望的方式对项目进行分组的密钥,然后使用generate-id()技巧来处理只是带有每个键值的第一个项。

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

  <xsl:key name="rowByName" match="Row" use="@name" />

  <xsl:template match="/">
    <table>
      <!-- apply templates for the first Row with each name -->
      <xsl:apply-templates select="query/Rows/Row[generate-id() =
          generate-id(key('rowByName', @name)[1])]" />
    </table>
  </xsl:template>

  <xsl:template match="Row">
    <tr>
      <td><xsl:value-of select="@name" /></td>
      <td>
        <!-- concatenate the title attributes of all rows with this name -->
        <xsl:for-each select="key('rowByName', @name)">
          <xsl:if test="position() &gt; 1">, </xsl:if>
          <xsl:value-of select="@title" />
        </xsl:for-each>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>