Xslt转换为每个

时间:2009-10-20 22:27:52

标签: xslt

有人可以帮助我进行以下转换吗?

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

,这里是输出ID,如

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

2 个答案:

答案 0 :(得分:1)

更自然的解决方案:

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

请注意,我使用模板模式使用相同的输入执行不同的操作。

结果是:

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

答案 1 :(得分:0)

这很贴心。虽然我已经完成了XSLT,但对我来说已经过了几年 - 忽略不好的风格。

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