XSLT 1.0 - 使用基于单独 XML 元素的两个表构建 XML 电子表格

XSLT 1.0 - Build an XML spreadsheet with two tables based on separate XML elements

我需要从 XML 文档构建一个特定格式的 XML Spreadsheet (SpreadsheetML) 文件,该文件包含单独构建的数据元素(使用 XSLT 1.0)。简化示例如下:

<Root>
<DetailsTable>
    <row data="1"/>
    <row data="2"/>
    <row data="3"/>
    <row data="4"/>
    <row data="5"/>
    <row data="6"/>
    <row data="7"/>
    <row data="8"/>
    <row data="9"/>
    <row data="10"/>
    <row data="11"/>
    <row data="12"/>
    <row data="13"/>
    <row data="14"/>
</DetailsTable>

<SummaryTable>
    <row data="A"/>
    <row data="B"/>
    <row data="C"/>
</SummaryTable>    
</Root>

所需的输出应该在 Excel sheet 上作为两个单独的 'tables' 布局,其中一个在另一个中间 - 如截图:

问题是,对于 XSLT 转换,我需要逐行打印,并且所有单元格都必须在打印行时打印 - 因此,对于某些行(例如索引 4、5、6、 7) 我需要添加一些特殊的单元格,我将从 SummaryTable XML 元素中获取这些值。

换句话说,输出 XML 格式是这样的:

    <Table>
   <Row>
    <Cell><Data >DetailsTable</Data></Cell>
   </Row>
   <Row>
    <Cell><Data >1</Data></Cell>
   </Row>
   <Row>
    <Cell><Data >2</Data></Cell>
   </Row>
   <Row>
    <Cell><Data >3</Data></Cell>
    <Cell><Data >SummaryTable</Data></Cell>
   </Row>
   <Row>
    <Cell><Data >4</Data></Cell>
    <Cell><Data >A</Data></Cell>
   </Row>
   <Row>
    <Cell><Data >5</Data></Cell>
    <Cell><Data >B</Data></Cell>
   </Row>
   <Row>
    <Cell><Data >6</Data></Cell>
    <Cell><Data >C</Data></Cell>
   </Row>
   <Row>
    <Cell><Data >7</Data></Cell>
   </Row>
   <Row>
    <Cell><Data >8</Data></Cell>
   </Row>
   <Row>
</Table>

问题是我无法控制详细信息中会有多少行 table - 只需对它们执行 'for-each' 并添加额外的单元格元素就足够了使用 position().

的特定索引

然而可能是太少(例如只有一个行元素)在这种情况下 for-each 永远不会迭代到索引 4、5、6、7,所以我的总结 table 不会被打印 - 这种情况下的预期输出应该是:

我正在考虑执行 for-each 循环指定的次数(例如 7),以便打印出前七行以及摘要 table,然后执行 for-each 再次循环 DetailsTable/row 元素,但跳过前 7 个索引位置,但这似乎是一个令人讨厌的解决方法。

还有其他想法吗?

一个解决方案,虽然它看起来不是很优雅,但是有一个递归模板,它递增行号直到它到达详细信息或摘要行的末尾,具体取决于哪个更大。

试试这个 XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>

  <xsl:param name="firstSummaryRow" select="4" />

  <xsl:variable name="lastDetailRow" select="1 + count(/*/DetailsTable/row)" />
  <xsl:variable name="lastSummaryRow" select="$firstSummaryRow + count(/*/SummaryTable/row)" />

  <xsl:template match="/*">
    <xsl:call-template name="Rows" />
  </xsl:template>

  <xsl:template name="Rows">
    <xsl:param name="rowNumber" select="1" />
    <Row>
      <Cell>
        <Data>
          <xsl:choose>
            <xsl:when test="$rowNumber = 1">Details Table</xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="DetailsTable/row[position() = $rowNumber - 1]/@data" />
            </xsl:otherwise>
          </xsl:choose>
        </Data>
      </Cell>
      <xsl:if test="$rowNumber >= $firstSummaryRow and $rowNumber &lt;= $lastSummaryRow">
        <Cell Index="3">
          <Data>
            <xsl:choose>
              <xsl:when test="$rowNumber = $firstSummaryRow">Summary Table</xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="SummaryTable/row[position() = $rowNumber - $firstSummaryRow]/@data" /> 
              </xsl:otherwise>
            </xsl:choose>
          </Data>
        </Cell>
      </xsl:if>
    </Row>
    <xsl:if test="$rowNumber &lt; $lastDetailRow or $rowNumber &lt; $lastSummaryRow">
      <xsl:call-template name="Rows">
        <xsl:with-param name="rowNumber" select="$rowNumber + 1" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

http://xsltfiddle.liberty-development.net/pPzifpd

查看实际效果