将Excel的SUM()添加到XLST结果页面?

如何将SUM()函数应用于每个hours节点? 我将保存这个transfomred XML为Excel,我希望它有embeddedSUM()函数。 经过研究,似乎有这么多的方法来做,但没有真正适用于我的问题。

XSL:

 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <body> <img src="../images/company_logo.png"></img> <p>Company: <xsl:value-of select="companies/company[1]/companyName"/></p> <p>Date: <xsl:value-of select="companies/company[1]/startDate"/> to <xsl:value-of select="companies/row[last()]/endDate"/></p> <table> <xsl:for-each select="company/row"> <tr> <td>ID:</td> <td><xsl:value-of select="serviceID"/></td> <td>Hours:</td> <td><xsl:value-of select="hours"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet> 

XML

 <company> <companyName>Cool Beans</companyName> <serviceID>1</serviceID> <startDate>01-01-2014 00:00:00</startDate> <endDate>01-02-2014 00:00:00</endDate> <hours>2</hours> </company> 

假设你有这样一个文件:

 <companies name="My Companies"> <company> <companyName>Cool Beans</companyName> <serviceID>1</serviceID> <startDate>01-01-2014 00:00:00</startDate> <endDate>01-02-2014 00:00:00</endDate> <hours>2</hours> </company> <company> <companyName>Hot Beans</companyName> <serviceID>2</serviceID> <startDate>01-01-2014 00:00:00</startDate> <endDate>01-02-2014 00:00:00</endDate> <hours>2</hours> </company> <company> <companyName>Evil Beans</companyName> <serviceID>3</serviceID> <startDate>01-03-2014 00:00:00</startDate> <endDate>01-04-2014 00:00:00</endDate> <hours>2</hours> </company> </companies> 

您将不得不生成有效的XLS或XSLX文件。 我将以[此Office 2003]( http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats )格式为例(XLS)。

您的样式表必须声明所有可能需要的前缀和名称空间,以确保电子表格中的属性和元素的质量。 您可以简单地在XSLT中声明它们,并将它们复制到您的结果文件中:

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> ... </xsl:stylesheet> 

您需要生成一个应该在文档根元素之前出现的mso-application 处理指令 。 我们可以为此创build一个模板:

 <xsl:template match="/"> <xsl:processing-instruction name="mso-application">progid="Excel.Sheet"</xsl:processing-instruction> <Workbook> <xsl:apply-templates select="companies" /> </Workbook> </xsl:template> 

这个模板会匹配root,因此会被处理一次 。 它将调用将处理样式表的其余部分的companies元素。 这是一个最小的模板。 你也可以放置你的元数据标签,样式等等。

我们也可以将工作表代码放在根模板中。 我决定分开它,以避免大模板。 因为只有一个companies节点,所以这个只能处理一次。 它将创build一个WorkSheet ,一个Table并调用其他一些模板来处理单独的行和单元格。

 <xsl:template match="companies"> <Worksheet ss:Name="{@name}"> <Table x:FullColumns="1" x:FullRows="1"> <Row><!-- Header Row --> <xsl:apply-templates select="company[1]/*" mode="headers"/> </Row> <xsl:apply-templates select="company" /> <Row><!-- Last Row --> <Cell ss:Index="4"><Data ss:Type="String">Total:</Data></Cell> <Cell ss:Formula="=SUM(R[-{count(company)}]C:R[-1]C)"> <Data ss:Type="Number"></Data> </Cell> </Row> </Table> </Worksheet> </xsl:template> 

第一行将包含标题。 由于XML源没有标题名称,因此我们将使用第一个company的子元素名称 (在单独的模板中完成)创build它们。 单独的行和单元格也将在单独的模板中处理,但在这里我们创build最后一行。 我们在第4列中放置一个单元格以打印文本“Total:”,并在下一行中插入一个Excel公式,该公式将总结前n行,其中ncompany总节点( R(-n)C:R(-1)C将评估为E2:E4并读取像:“ 从这一行计数(公司)这一行 – 1”)。

其他模板为每一行和数据单元创build代码,使用ss:Type信息(您要求和的字段必须是Numbertypes)。

这里是完整的样式表:

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <xsl:output method="xml" indent="yes" /> <xsl:template match="/"> <xsl:processing-instruction name="mso-application">progid="Excel.Sheet"</xsl:processing-instruction> <Workbook> <xsl:apply-templates select="companies" /> </Workbook> </xsl:template> <xsl:template match="companies"> <Worksheet ss:Name="{@name}"> <Table x:FullColumns="1" x:FullRows="1"> <Row><!-- Header Row --> <xsl:apply-templates select="company[1]/*" mode="headers"/> </Row> <xsl:apply-templates select="company" /> <Row><!-- Last Row --> <Cell ss:Index="4"><Data ss:Type="String">Total:</Data></Cell> <Cell ss:Formula="=SUM(R[-{count(company)}]C:R[-1]C)"> <Data ss:Type="Number"></Data> </Cell> </Row> </Table> </Worksheet> </xsl:template> <xsl:template match="company[1]/*" mode="headers"> <Cell> <Data ss:Type="String"> <xsl:value-of select="name()" /> </Data> </Cell> </xsl:template> <xsl:template match="company"> <Row> <xsl:apply-templates select="*" /> </Row> </xsl:template> <xsl:template match="companyName|serviceID|startDate|endDate"> <Cell> <Data ss:Type="String"> <xsl:value-of select="."/> </Data> </Cell> </xsl:template> <xsl:template match="hours"> <Cell> <Data ss:Type="Number"> <xsl:value-of select="."/> </Data> </Cell> </xsl:template> </xsl:stylesheet> 

将结果保存为扩展名为.xls的文件( 不是 .xslx ),然后在Excel中打开。 您将拥有一个电子表格,其中包含一个名为“我的公司”的工作表,表格中的每个字段以及最后一行/列中的总计小时数(以Excel公式计算)。

这里是一个包含该样式表的小提琴应用于我在这个答案的开头提供的源代码(可能类似于你的源代码)。 以下是结果列表:

 <?xml version="1.0" encoding="UTF-8"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Worksheet ss:Name="My Companies"> <Table x:FullColumns="1" x:FullRows="1"> <Row> <Cell> <Data ss:Type="String">companyName</Data> </Cell> <Cell> <Data ss:Type="String">serviceID</Data> </Cell> <Cell> <Data ss:Type="String">startDate</Data> </Cell> <Cell> <Data ss:Type="String">endDate</Data> </Cell> <Cell> <Data ss:Type="String">hours</Data> </Cell> </Row> <Row> <Cell> <Data ss:Type="String">Cool Beans</Data> </Cell> <Cell> <Data ss:Type="String">1</Data> </Cell> <Cell> <Data ss:Type="String">01-01-2014 00:00:00</Data> </Cell> <Cell> <Data ss:Type="String">01-02-2014 00:00:00</Data> </Cell> <Cell> <Data ss:Type="Number">2</Data> </Cell> </Row> <Row> <Cell> <Data ss:Type="String">Hot Beans</Data> </Cell> <Cell> <Data ss:Type="String">2</Data> </Cell> <Cell> <Data ss:Type="String">01-01-2014 00:00:00</Data> </Cell> <Cell> <Data ss:Type="String">01-02-2014 00:00:00</Data> </Cell> <Cell> <Data ss:Type="Number">2</Data> </Cell> </Row> <Row> <Cell> <Data ss:Type="String">Evil Beans</Data> </Cell> <Cell> <Data ss:Type="String">3</Data> </Cell> <Cell> <Data ss:Type="String">01-03-2014 00:00:00</Data> </Cell> <Cell> <Data ss:Type="String">01-04-2014 00:00:00</Data> </Cell> <Cell> <Data ss:Type="Number">2</Data> </Cell> </Row> <Row> <Cell ss:Index="4"> <Data ss:Type="String">Total:</Data> </Cell> <Cell ss:Formula="=SUM(R[-3]C:R[-1]C)"> <Data ss:Type="Number"/> </Cell> </Row> </Table> </Worksheet> </Workbook> 

这是在Excel 2011 for Mac 2011中加载后的结果文件的屏幕截图:

加载到Excel 2011 for Mac 2011后的结果

点击Row(5)Col(5)或者E5 )的位置,你应该看到它存储了Excel公式,它使用Row(5-3)Col(5):Row(5-1)Col(5)数据正确添加了3字段Row(5-3)Col(5):Row(5-1)Col(5)E2:E4 ):

显示Excel公式已正确生成