开发者

Xslt transformation for-each

Could anyone help me with the 开发者_如何学Cfollowing transformation?

Here is the XML

<Chart>
<Chart.Series>
    <DataSeries LegendText="Complete On Time"  >
        <DataSeries.DataPoints>
            <DataPoint AxisXLabel="Sep 09" YValue="10" />
            <DataPoint AxisXLabel="Oct 09" YValue="11" />
            <DataPoint AxisXLabel="Nov 09" YValue="12" />
        </DataSeries.DataPoints>
    </DataSeries>

    <DataSeries LegendText="Complete Overdue"  >
        <DataSeries.DataPoints>
            <DataPoint  YValue="1" />
            <DataPoint  YValue="2" />
            <DataPoint  YValue="3" />
        </DataSeries.DataPoints>
    </DataSeries>
</Chart.Series>
</Chart>

and here is the output id like

<table>
<thead>
    <tr>
        <th></th>
        <th>Complete On Time</th>
        <th>Complete Overdue</th>
    </tr>
</thead>
<tbody>
    <tr>
        <th>Sep 09</th>
        <th>10</th>
        <th>1</th>
    </tr>
    <tr>
        <th>Oct 09</th>
        <th>11</th>
        <th>2</th>
    </tr>
    <tr>
        <th>Nov 09</th>
        <th>12</th>
        <th>3</th>
    </tr>
</tbody>


A more natural solution:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <!-- basic table structure -->
  <xsl:template match="Chart">
    <table>
      <thead>
        <xsl:apply-templates select="Chart.Series" mode="thead" />
      </thead>
      <tbody>
        <xsl:apply-templates select="Chart.Series" mode="tbody" />
      </tbody>
    </table>
  </xsl:template>

  <!-- table head -->
  <xsl:template match="Chart.Series" mode="thead">
    <tr>
      <th />
      <xsl:for-each select="DataSeries">
        <th>
          <xsl:value-of select="@LegendText" />
        </th>
      </xsl:for-each>  
    </tr>
  </xsl:template>

  <!-- table body -->
  <xsl:template match="Chart.Series" mode="tbody">
    <xsl:variable name="ds" select="DataSeries" />

    <!-- the first data series contains the labels -->
    <xsl:for-each select="$ds[1]/*/DataPoint">
      <xsl:variable name="pos" select="position()" />
      <tr>
        <td>
          <xsl:value-of select="@AxisXLabel" />
        </td>
        <!-- process all data points at the current position -->
        <xsl:apply-templates select="$ds/*/DataPoint[$pos]" />
      </tr>
    </xsl:for-each>
  </xsl:template>

  <!-- data points become a <td> -->
  <xsl:template match="DataPoint">
    <td>
      <xsl:value-of select="@YValue" />
    </td>
  </xsl:template>
</xsl:stylesheet>

Note that I use template modes to do different things with the same input.

The result is:

<table>
  <thead>
    <tr>
      <th />
      <th>Complete On Time</th>
      <th>Complete Overdue</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sep 09</td>
      <td>10</td>
      <td>1</td>
    </tr>
    <tr>
      <td>Oct 09</td>
      <td>11</td>
      <td>2</td>
    </tr>
    <tr>
      <td>Nov 09</td>
      <td>12</td>
      <td>3</td>
    </tr>
  </tbody>
</table>


This is something close. It's been a couple of year for me though that I've done XSLT - ignore bad style.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output indent="yes" omit-xml-declaration="yes" ></xsl:output>
<xsl:template match="/">
    <table>
        <thead>
                <tr>
                        <th></th>
                        <xsl:apply-templates select=".//DataSeries" />
                </tr>
        </thead>
        <tbody>
            <xsl:apply-templates select="//DataSeries[1]//DataPoint">
                <xsl:with-param name="datablock">1</xsl:with-param>
            </xsl:apply-templates>
        </tbody>
    </table>
</xsl:template>
<xsl:template match="DataSeries">
    <th>
        <xsl:value-of select="@LegendText"></xsl:value-of>
    </th>
</xsl:template>
<xsl:template match="DataPoint">
    <xsl:param name="datablock" />
    <xsl:variable name="posi" select="position()"></xsl:variable>
    <xsl:if test="$datablock = 1">
        <tr>
            <xsl:for-each select="@*">
            <th>
                <xsl:value-of select="."></xsl:value-of>
            </th>
        </xsl:for-each>     
        <xsl:apply-templates select="//DataSeries[$datablock+1]//DataPoint[$posi]">
                <xsl:with-param name="datablock" select="$datablock + 1">
                </xsl:with-param>
        </xsl:apply-templates>
        </tr>
    </xsl:if>
    <xsl:if test="$datablock != 1">
        <xsl:for-each select="@*">
            <th>
                <xsl:value-of select="."></xsl:value-of>
            </th>
        </xsl:for-each>     
        <xsl:apply-templates select="//DataSeries[$datablock+1]//DataPoint[$posi]">
                <xsl:with-param name="datablock" select="$datablock + 1">
                </xsl:with-param>
        </xsl:apply-templates>
    </xsl:if>
</xsl:template>

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜