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 <= $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 < $lastDetailRow or $rowNumber < $lastSummaryRow">
<xsl:call-template name="Rows">
<xsl:with-param name="rowNumber" select="$rowNumber + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
查看实际效果
我需要从 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 <= $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 < $lastDetailRow or $rowNumber < $lastSummaryRow">
<xsl:call-template name="Rows">
<xsl:with-param name="rowNumber" select="$rowNumber + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
查看实际效果