开发者

How to extract the "for eached" element's child elements only with XSLT

I want to diplay a set of tables from an XML file defined as follows:

<reportStructure>
  <table>
    <headers>
      <tableHeader>Header 1.1</tableHeader>
      <tableHeader>Header 1.2</tableHeader>
    </headers>
    <tuples>
      <tuple>
        <tableCell>1.1.1</tableCell>
        <tableCell>1.2.1</tableCell>
      </tuple>
      <tuple>
        <tableCell>1.1.2</tableCell>
        <tableCell>1.2.2</tableCell>
      </tuple>
    </tuples>
  </table>
  <table>
  ...

I am using XSLT and XPath to transform the data, but the foreach does not work the way I expect it to:

      <xsl:template match="reportStructure">
        <xsl:for-each select="table">
          <table>
            <tr>
              <xsl:apply-templates select="/reportStructure/table/headers"/>
            </tr>
            <xsl:apply-templates select="/reportStructure/table/tuples/tuple"/>
          </table>      
        </xsl:for-each>
      </xsl:template>

      <xsl:template match="headers">
        <xsl:for-each select="tableHeader">
          <th>
            <xsl:value-of select="." />
          </th>
        </xsl:for-each>
      </xsl:template

      <xsl:template match="tuple">
        <tr>
          <xsl:for-each select="tableCell">
            <td>
              <xsl:value-of select="." />
            </td>
          </xsl:for-each>
        </tr>
      </xsl:template>

While I would expect this to output one table per table-tag, it outputs all the table headers and cells 开发者_JAVA百科for each table-tag.


You are selecting all headers and tuples in your apply-templates.

Select the relevant ones only:

  <xsl:template match="reportStructure">
    <xsl:for-each select="table">
      <table>
        <tr>
          <xsl:apply-templates select="headers"/>
        </tr>
        <xsl:apply-templates select="tuples/tuple"/>
      </table>      
    </xsl:for-each>
  </xsl:template>

You should really also simply have the above as a single table template, without the xsl:for-each:

  <xsl:template match="table">
      <table>
        <tr>
          <xsl:apply-templates select="headers"/>
        </tr>
        <xsl:apply-templates select="tuples/tuple"/>
      </table>      
  </xsl:template>


Beside @Oded's good answer, this shows why a "push style" is more... reusable:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="table">
        <table>
            <xsl:apply-templates/>
        </table>
    </xsl:template>
    <xsl:template match="headers|tuple">
        <tr>
            <xsl:apply-templates/>
        </tr>
    </xsl:template>
    <xsl:template match="tableHeader">
        <th>
            <xsl:apply-templates/>
        </th>
    </xsl:template>
    <xsl:template match="tableCell">
        <td>
            <xsl:apply-templates/>
        </td>
    </xsl:template>
</xsl:stylesheet>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜