如何使用XSLT1.0将spreadsheetML标记扩展为常规矩阵标记



使用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 &lt;= 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>

让我们知道的进展情况

相关内容

  • 没有找到相关文章

最新更新