使用Excel 2007生成的spreadsheetML(以及以后的更新版本),xl:Row和xl:Cell元素可能包括ss:Index的属性,该属性提供"跳过"完全空白单元格的行或列名称。这使得spreadsheetML中的标记更小,但当试图根据规则几何体来评估矩阵时是不方便的,其中矩阵中实际存在空白单元格。
我在msxml中制作了一个XSLT1.0例程,它将例如<xsl:Row><xl:Cell ss:Index="3">dave</xl:Cell></xl:Row>
类型的传入标记转换为类似以下的"扩展"形式:
<Row>
<Col/><Col/><Col>dave</Col>
</Row>
请注意,"空白"单元格将转换为一个空的自关闭标记。这很有帮助,因为接下来的XSLT可以假设行和列出现在Row/Col结构中的正确序号位置。
然而,这个过程很复杂,而且有点慢。有人通过其他机制解决过"打开"ss:Index值的挑战吗?您必须假设传入数据中可能存在"空白单元格"。
我的处理平台是ASP经典的Jscript,它在ASP、msxml内部运行,并将结果返回给浏览器。然而,任何和所有的视角都是受欢迎的,不受本平台描述的约束。理想情况下,解包过程发生在服务器上,因为序列化的XSLT会对结果进行操作。
谢谢各位读者!
XML结构不是您希望它在电子表格中的样子。我经历了痛苦来解决这个问题(MK在某个时候加入了进来)。你大致需要的是这样的(里面还有一些检查):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:e="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" exclude-result-prefixes="e ss">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:param name="sheetname">Sheet1</xsl:param>
<xsl:template match="e:Workbook">
<xsl:element name="importdata">
<xsl:attribute name="type"><xsl:value-of select="$sheetname"/></xsl:attribute>
<xsl:apply-templates select="e:Worksheet[@ss:Name=$sheetname]"/>
</xsl:element>
</xsl:template>
<xsl:template match="e:Worksheet">
<xsl:apply-templates select="e:Table/e:Row"/>
</xsl:template>
<xsl:template match="ss:Row">
<xsl:if test="not(ss:Cell[1]/@ss:Index)">
<!-- We do NOT process records where the first cell is empty -->
<xsl:element name="record">
<xsl:attribute name="position"><xsl:value-of select="position()-1"/></xsl:attribute>
<xsl:apply-templates select="e:Cell"/>
</xsl:element>
</xsl:if>
</xsl:template>
<xsl:template match="ss:Cell">
<xsl:variable name="curCol">
<xsl:choose>
<xsl:when test="@ss:Index">
<xsl:value-of select="@ss:Index"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="cell-index">
<xsl:with-param name="idx" select="1"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="field">
<xsl:attribute name="col"><xsl:value-of select="$curCol"/></xsl:attribute>
<xsl:attribute name="name"><xsl:value-of select="normalize-space(ancestor::e:Table/e:Row[position()=1]/e:Cell[position()=$curCol])"/></xsl:attribute>
<xsl:value-of select="ss:Data"/>
</xsl:element>
</xsl:template>
<xsl:template name="cell-index">
<xsl:param name="idx"/>
<xsl:if test="$idx <= position()">
<xsl:choose>
<xsl:when test="preceding-sibling::ss:Cell[position()=$idx]/@ss:Index">
<xsl:value-of select="preceding-sibling::ss:Cell[position()=$idx]/@ss:Index +$idx"/>
</xsl:when>
<xsl:when test="$idx = position()">
<xsl:value-of select="$idx"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="cell-index">
<xsl:with-param name="idx" select="$idx+1"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<!-- We don't process the first row since it has the field names in it -->
<xsl:template match="ss:Row[position()=1]"/>
</xsl:stylesheet>
让我们知道的进展情况