如何输出比输入更多的列
How to output more columns than input
鉴于此打开 XML 片段:
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<Worksheet ss:Name="Sheet5">
<Table ss:ExpandedColumnCount="7" ss:ExpandedRowCount="4">
<Column ss:Index="2" ss:AutoFitWidth="0" ss:Width="59.25"/>
<Column ss:Index="5" ss:AutoFitWidth="0" ss:Width="75"/>
<Column ss:AutoFitWidth="0" ss:Width="31.5"/>
</Table>
</Worksheet>
</Workbook>
...我可以使用什么 XSLT 1.0 模板解决方案(尽可能避免循环)来生成此 HTML 输出片段:
<table>
<colgroup>
<col style="width:45pt;">
<col style="width:59.25pt;">
<col style="width:45pt;">
<col style="width:45pt;">
<col style="width:75pt;">
<col style="width:31.5pt;">
<col style="width:45pt;">
</colgroup>
</table>
请注意,ss:ExpandedColumnCount 属性指定总列数。另请注意,源代码中不包含 ss:Index 的 Column 标记是一种特殊情况,它指定前一列之后的下一列索引指数;在这种情况下,它的计算结果为 6。所有其他列的宽度均假定为 45pt。
在我的环境中,别无选择,只能使用 MSXML2 引擎。
这只是 MS Excel 工作表上范围选择的任意示例,工作表以 Open XML 编码,有时称为 OOXML。我正在寻找 XLST 在一般情况下执行此转换。
我不确定“尽可能避免循环”到底是什么意思。如果不使用 recursion,我当然看不出这是如何实现的。事实上,我相信你需要在两个地方使用它:
首先,生成覆盖列宽的列表,其中每个节点都有一个索引值;
然后,生成所需数量的col
个元素。
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
exclude-result-prefixes="ss"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ss:Table">
<xsl:variable name="col-widths-rtf">
<xsl:apply-templates select="ss:Column[1]" mode="col-widths"/>
</xsl:variable>
<table>
<colgroup>
<xsl:call-template name="colgroup">
<xsl:with-param name="n" select="@ss:ExpandedColumnCount"/>
<xsl:with-param name="col-widths" select="exsl:node-set($col-widths-rtf)/width"/>
</xsl:call-template>
</colgroup>
</table>
</xsl:template>
<xsl:template match="ss:Column" mode="col-widths">
<xsl:param name="last-index" select="0"/>
<xsl:variable name="index">
<xsl:choose>
<xsl:when test="@ss:Index">
<xsl:value-of select="@ss:Index"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$last-index + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<width index="{$index}">
<xsl:value-of select="@ss:Width"/>
</width>
<!-- sibling recursion -->
<xsl:apply-templates select="following-sibling::ss:Column[1]" mode="col-widths">
<xsl:with-param name="last-index" select="$index"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="colgroup">
<xsl:param name="n"/>
<xsl:param name="col-widths"/>
<xsl:variable name="override" select="$col-widths[@index=$n]" />
<xsl:variable name="width">
<xsl:choose>
<xsl:when test="$override">
<xsl:value-of select="$override"/>
</xsl:when>
<xsl:otherwise>45</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="$n > 1">
<!-- recursive call -->
<xsl:call-template name="colgroup">
<xsl:with-param name="n" select="$n - 1"/>
<xsl:with-param name="col-widths" select="$col-widths"/>
</xsl:call-template>
</xsl:if>
<col style="width:{$width}pt;"/>
</xsl:template>
</xsl:stylesheet>
我认为它可以在没有扩展函数的情况下完成,并且一次通过,但我可能是错的,因为我没有在所有可能的情况下完全测试以下 XSLT,但无论如何都要试一试。 ..
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
exclude-result-prefixes="ss">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="ss:Table">
<table>
<colgroup>
<xsl:call-template name="Columns" />
</colgroup>
</table>
</xsl:template>
<xsl:template name="Columns">
<xsl:param name="MaxColumns" select="@ss:ExpandedColumnCount" />
<xsl:param name="Column" select="ss:Column[1]" />
<xsl:param name="ColumnNumber" select="1" />
<xsl:if test="$ColumnNumber <= $MaxColumns">
<xsl:variable name="IsMatch" select="$Column/@ss:Index = $ColumnNumber or $Column[not(@ss:Index)]" />
<xsl:variable name="width">
<xsl:choose>
<xsl:when test="$IsMatch">
<xsl:value-of select="$Column/@ss:Width" />
</xsl:when>
<xsl:otherwise>45</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<col style="width:{$width}pt;"></col>
<xsl:call-template name="Columns">
<xsl:with-param name="MaxColumns" select="$MaxColumns" />
<xsl:with-param name="Column" select="$Column[not($IsMatch)]|$Column[$IsMatch]/following-sibling::ss:Column[1]" />
<xsl:with-param name="ColumnNumber" select="$ColumnNumber + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
鉴于此打开 XML 片段:
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<Worksheet ss:Name="Sheet5">
<Table ss:ExpandedColumnCount="7" ss:ExpandedRowCount="4">
<Column ss:Index="2" ss:AutoFitWidth="0" ss:Width="59.25"/>
<Column ss:Index="5" ss:AutoFitWidth="0" ss:Width="75"/>
<Column ss:AutoFitWidth="0" ss:Width="31.5"/>
</Table>
</Worksheet>
</Workbook>
...我可以使用什么 XSLT 1.0 模板解决方案(尽可能避免循环)来生成此 HTML 输出片段:
<table>
<colgroup>
<col style="width:45pt;">
<col style="width:59.25pt;">
<col style="width:45pt;">
<col style="width:45pt;">
<col style="width:75pt;">
<col style="width:31.5pt;">
<col style="width:45pt;">
</colgroup>
</table>
请注意,ss:ExpandedColumnCount 属性指定总列数。另请注意,源代码中不包含 ss:Index 的 Column 标记是一种特殊情况,它指定前一列之后的下一列索引指数;在这种情况下,它的计算结果为 6。所有其他列的宽度均假定为 45pt。
在我的环境中,别无选择,只能使用 MSXML2 引擎。
这只是 MS Excel 工作表上范围选择的任意示例,工作表以 Open XML 编码,有时称为 OOXML。我正在寻找 XLST 在一般情况下执行此转换。
我不确定“尽可能避免循环”到底是什么意思。如果不使用 recursion,我当然看不出这是如何实现的。事实上,我相信你需要在两个地方使用它:
首先,生成覆盖列宽的列表,其中每个节点都有一个索引值;
然后,生成所需数量的
col
个元素。
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
exclude-result-prefixes="ss"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ss:Table">
<xsl:variable name="col-widths-rtf">
<xsl:apply-templates select="ss:Column[1]" mode="col-widths"/>
</xsl:variable>
<table>
<colgroup>
<xsl:call-template name="colgroup">
<xsl:with-param name="n" select="@ss:ExpandedColumnCount"/>
<xsl:with-param name="col-widths" select="exsl:node-set($col-widths-rtf)/width"/>
</xsl:call-template>
</colgroup>
</table>
</xsl:template>
<xsl:template match="ss:Column" mode="col-widths">
<xsl:param name="last-index" select="0"/>
<xsl:variable name="index">
<xsl:choose>
<xsl:when test="@ss:Index">
<xsl:value-of select="@ss:Index"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$last-index + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<width index="{$index}">
<xsl:value-of select="@ss:Width"/>
</width>
<!-- sibling recursion -->
<xsl:apply-templates select="following-sibling::ss:Column[1]" mode="col-widths">
<xsl:with-param name="last-index" select="$index"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="colgroup">
<xsl:param name="n"/>
<xsl:param name="col-widths"/>
<xsl:variable name="override" select="$col-widths[@index=$n]" />
<xsl:variable name="width">
<xsl:choose>
<xsl:when test="$override">
<xsl:value-of select="$override"/>
</xsl:when>
<xsl:otherwise>45</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="$n > 1">
<!-- recursive call -->
<xsl:call-template name="colgroup">
<xsl:with-param name="n" select="$n - 1"/>
<xsl:with-param name="col-widths" select="$col-widths"/>
</xsl:call-template>
</xsl:if>
<col style="width:{$width}pt;"/>
</xsl:template>
</xsl:stylesheet>
我认为它可以在没有扩展函数的情况下完成,并且一次通过,但我可能是错的,因为我没有在所有可能的情况下完全测试以下 XSLT,但无论如何都要试一试。 ..
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
exclude-result-prefixes="ss">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="ss:Table">
<table>
<colgroup>
<xsl:call-template name="Columns" />
</colgroup>
</table>
</xsl:template>
<xsl:template name="Columns">
<xsl:param name="MaxColumns" select="@ss:ExpandedColumnCount" />
<xsl:param name="Column" select="ss:Column[1]" />
<xsl:param name="ColumnNumber" select="1" />
<xsl:if test="$ColumnNumber <= $MaxColumns">
<xsl:variable name="IsMatch" select="$Column/@ss:Index = $ColumnNumber or $Column[not(@ss:Index)]" />
<xsl:variable name="width">
<xsl:choose>
<xsl:when test="$IsMatch">
<xsl:value-of select="$Column/@ss:Width" />
</xsl:when>
<xsl:otherwise>45</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<col style="width:{$width}pt;"></col>
<xsl:call-template name="Columns">
<xsl:with-param name="MaxColumns" select="$MaxColumns" />
<xsl:with-param name="Column" select="$Column[not($IsMatch)]|$Column[$IsMatch]/following-sibling::ss:Column[1]" />
<xsl:with-param name="ColumnNumber" select="$ColumnNumber + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>