如何仅使用XSLT提取“for each”元素的子元素

时间:2010-11-11 19:18:32

标签: xml xslt xpath

我想从XML文件中显示一组表,如下所示:

<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>
  ...

我正在使用XSLT和XPath来转换数据,但是foreach并不像我期望的那样工作:

      <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>

虽然我希望每个table-tag输出一个表,但它会输出每个table-tag的所有表头和单元格。

2 个答案:

答案 0 :(得分:6)

您正在apply-templates中选择所有标题和元组。

仅选择相关的:

  <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>

您还应该简单地将上述内容作为单个table模板,而不是xsl:for-each

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

答案 1 :(得分:2)

除了@ Oded的好答案之外,这也说明为什么“推送风格”更具......可重复使用:

<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>