1

我的 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 样式表,但第一个之前的打开似乎会导致结构无效,因此页面无法加载。

<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 的结构不是很好,但我对数据源没有影响。

4

2 回答 2

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>
于 2013-06-26T13:29:09.463 回答
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>
于 2013-06-26T12:08:04.440 回答