[b]3. XSLT 解析XML为表格型XML的实例(具体请参考附件)[/b]
[color=blue]* 感兴趣的人可以去下个Eclipse Xslt插件:[b]Orangevolt XSLT[/b]。它可以帮助你使用指定的xsl解析指定的xml,无须写java代码。[/color]
[b]需求:[/b]根据下面xml中的各中心/部门/科室的收入支出数据,生成一张电子表格,要求同一个中心或者同一个部门的数据的单元格要能合并
[b](这个是非常简单的一个需求,我们就从这个简单需求入手,看看需要如何操作达到目的)[/b]
[b]提供的源数据XML:参考附件中的DepInOutData.xml[/b]
下面我就直接给出关键的XSLT代码(具体请参考附件中的Pattern.xsl):
[b]附件中[/b](放心,俺的开发机杀毒软件具备,一般都杀完毒才放心发布的)
有解析后的结果:DepInOutDataResult.xml,使用MS Office2003以上版本打开可以查看。
[b] 首先有必要将上面的几个重要的常量解释下[/b]:
1. [b]ss:ExpandedColumnCount[/b]是定义表格的列数
测试中我发现这个数值必须[b][color=red]大于[/color][/b]实际的列数,例如在本例中,我的实际列数是[b]5列(中心/部门/科室/收入/支出)[/b],那么赋值的时候使用的是[b]6[/b], 如果使用的是5的话,解析的结果文件使用Office无法打开,提示格式错误信息,不信的同学可以尝试下:
2. [b]ss:ExpandedRowCount[/b]是定义表格的行数,当然肯定要[b][color=red]大于[/color][/b]实际的行数,这里我做了个算式:[b]统计出源数据xml中Section个数+10[/b]
3. [b]Column... [/b]标签是定义每一列的长宽等属性,实际列数是5列,那么就定义5个Column标签
4. [b]Row... [/b]标签是定义每一行的长宽等属性,实际行数是多少,那么就定义多少个Row标签
5. [b]Cell... [/b]标签是Row的子标签,用于定义每一行中各单元格的数据及样式等等
6. [b]xsl:call-template[/b]标签是调用函数的, 具体调用哪一个函数则通过属性[b][color=blue]name[/color][/b]指定。
本例中填充各项数据,合并单元格等操作都是在函数“Sections”及其子函数中完成
7. [b]ss:MergeAcross[/b]是Cell的属性, 用于单元格的横向合并
下面的例子表示:合并当前单元格右边的4个单元格(即横向区域总共5个单元格被合并)
8. [b]ss:MergeDown[/b]是Cell的属性, 用于单元格的纵向合并
下面的例子表示:合并当前单元格下边的4个单元格(即纵向区域总共5个单元格被合并)
[b] 以上即是关键部分,原本想就后面的函数多解释解释,但想来是没大必要的,不仅仅是简单的缘故,相信大家都是牛**的developer,所以解释的太多反倒不美。所以就此打住,刚接触xslt的同学参考例子多思考思考,多写写就可以了[/b]
附件内容:
1. DepInOutData.xml --- 源数据xml
2. Pattern.xsl --- xslt文件
3. DepInOutDataResult.xml ---解析结果
[color=blue]* 感兴趣的人可以去下个Eclipse Xslt插件:[b]Orangevolt XSLT[/b]。它可以帮助你使用指定的xsl解析指定的xml,无须写java代码。[/color]
[b]需求:[/b]根据下面xml中的各中心/部门/科室的收入支出数据,生成一张电子表格,要求同一个中心或者同一个部门的数据的单元格要能合并
[b](这个是非常简单的一个需求,我们就从这个简单需求入手,看看需要如何操作达到目的)[/b]
[b]提供的源数据XML:参考附件中的DepInOutData.xml[/b]
<?xml version="1.0" encoding="UTF-8"?>
<Report title="测试XSLT" >
<Sections>
<Center name="销售中心">
<Department name="销售1部">
<Section>
<SectionName value="销售1科"/>
<Input value="100.0"/>
<Output value="10.0"/>
</Section>
<Section>
<SectionName value="销售2科"/>
<Input value="101.0"/>
<Output value="12.0"/>
</Section>
<Section>
<SectionName value="销售3科"/>
<Input value="102.0"/>
<Output value="11.0"/>
</Section>
</Department>
<Department name="销售2部">
<Section>
<SectionName value="销售4科"/>
<Input value="100.0"/>
<Output value="10.0"/>
</Section>
<Section>
<SectionName value="销售5科"/>
<Input value="101.0"/>
<Output value="12.0"/>
</Section>
<Section>
<SectionName value="销售6科"/>
<Input value="102.0"/>
<Output value="11.0"/>
</Section>
</Department>
</Center>
<Center name="研发中心">
<Department name="研发1部">
<Section>
<SectionName value="研发1科"/>
<Input value="100.0"/>
<Output value="10.0"/>
</Section>
<Section>
<SectionName value="研发2科"/>
<Input value="101.0"/>
<Output value="12.0"/>
</Section>
<Section>
<SectionName value="研发3科"/>
<Input value="102.0"/>
<Output value="11.0"/>
</Section>
</Department>
<Department name="研发2部">
<Section>
<SectionName value="研发4科"/>
<Input value="0.0"/>
<Output value="50.0"/>
</Section>
<Section>
<SectionName value="研发5科"/>
<Input value="0.0"/>
<Output value="52.0"/>
</Section>
<Section>
<SectionName value="研发6科"/>
<Input value="0.0"/>
<Output value="51.0"/>
</Section>
</Department>
<Department name="测试1部">
<Section>
<SectionName value="测试1科"/>
<Input value="0.0"/>
<Output value="10.0"/>
</Section>
<Section>
<SectionName value="测试2科"/>
<Input value="0.0"/>
<Output value="12.0"/>
</Section>
<Section>
<SectionName value="测试3科"/>
<Input value="0.0"/>
<Output value="11.0"/>
</Section>
</Department>
</Center>
</Sections>
</Report>
下面我就直接给出关键的XSLT代码(具体请参考附件中的Pattern.xsl):
<xsl:for-each select="Report/Sections">
<!-- Create worksheet dynamically -->
<xsl:element name="Worksheet">
<xsl:attribute name="ss:Name">部门收入支出费用表</xsl:attribute>
<xsl:element name="Table">
<!-- ExpandedColumnCount 是表格的列数,>实际的数据的列数-->
<xsl:attribute name="ss:ExpandedColumnCount">6</xsl:attribute>
<!-- ExpandedRowCount 是表格的行数, >实际数据行数即可-->
<xsl:attribute name="ss:ExpandedRowCount">
<xsl:value-of select="count(.//Section)+10"/>
</xsl:attribute>
<xsl:attribute name="x:FullColumns">1</xsl:attribute>
<xsl:attribute name="x:FullRows">1</xsl:attribute>
<xsl:attribute name="ss:StyleID">s24</xsl:attribute>
<xsl:attribute name="ss:DefaultColumnWidth">90</xsl:attribute>
<xsl:attribute name="ss:DefaultRowHeight">18</xsl:attribute>
<Column ss:StyleID="s24" ss:AutoFitWidth="1" ss:Width="90"/>
<Column ss:StyleID="s24" ss:AutoFitWidth="1" ss:Width="90"/>
<Column ss:StyleID="s24" ss:AutoFitWidth="1" ss:Width="90"/>
<Column ss:StyleID="s24" ss:AutoFitWidth="1" ss:Width="90"/>
<Column ss:StyleID="s24" ss:AutoFitWidth="1" ss:Width="90"/>
<!-- 表格的Title-->
<Row ss:AutoFitHeight="1" ss:Height="18">
<Cell ss:MergeAcross="4" ss:StyleID="s121">
<Data ss:Type="String">
<xsl:value-of select="/Report/@title"/>
</Data>
</Cell>
</Row>
<Row ss:Height="29.25">
<Cell ss:StyleID="s28">
<Data ss:Type="String">
<xsl:value-of select="'总部'"/>
</Data>
</Cell>
<Cell ss:StyleID="s28">
<Data ss:Type="String">
<xsl:value-of select="'部门'"/>
</Data>
</Cell>
<Cell ss:StyleID="s28">
<Data ss:Type="String">
<xsl:value-of select="'科室'"/>
</Data>
</Cell>
<Cell ss:StyleID="s29">
<Data ss:Type="String">
<xsl:value-of select="'收入(万元)'"/>
</Data>
</Cell>
<Cell ss:StyleID="s29">
<Data ss:Type="String">
<xsl:value-of select="'支出(万元)'"/>
</Data>
</Cell>
</Row>
<xsl:if test="count(.//Section) > 0">
<xsl:call-template name="Sections"/>
</xsl:if>
</xsl:element>
</xsl:element>
</xsl:for-each>
[b]附件中[/b](放心,俺的开发机杀毒软件具备,一般都杀完毒才放心发布的)
有解析后的结果:DepInOutDataResult.xml,使用MS Office2003以上版本打开可以查看。
[b] 首先有必要将上面的几个重要的常量解释下[/b]:
1. [b]ss:ExpandedColumnCount[/b]是定义表格的列数
测试中我发现这个数值必须[b][color=red]大于[/color][/b]实际的列数,例如在本例中,我的实际列数是[b]5列(中心/部门/科室/收入/支出)[/b],那么赋值的时候使用的是[b]6[/b], 如果使用的是5的话,解析的结果文件使用Office无法打开,提示格式错误信息,不信的同学可以尝试下:
<xsl:attribute name="ss:ExpandedColumnCount">6</xsl:attribute>
2. [b]ss:ExpandedRowCount[/b]是定义表格的行数,当然肯定要[b][color=red]大于[/color][/b]实际的行数,这里我做了个算式:[b]统计出源数据xml中Section个数+10[/b]
<xsl:attribute name="ss:ExpandedRowCount">
<xsl:value-of select="count(.//Section)+10"/>
</xsl:attribute>
3. [b]Column... [/b]标签是定义每一列的长宽等属性,实际列数是5列,那么就定义5个Column标签
<Column ss:StyleID="s24" ss:AutoFitWidth="1" ss:Width="90"/>
4. [b]Row... [/b]标签是定义每一行的长宽等属性,实际行数是多少,那么就定义多少个Row标签
<Row ss:AutoFitHeight="1" ss:Height="18">
</Row>
5. [b]Cell... [/b]标签是Row的子标签,用于定义每一行中各单元格的数据及样式等等
<Cell ss:StyleID="s28">
<Data ss:Type="String">
<xsl:value-of select="'总部'"/>
</Data>
</Cell>
6. [b]xsl:call-template[/b]标签是调用函数的, 具体调用哪一个函数则通过属性[b][color=blue]name[/color][/b]指定。
本例中填充各项数据,合并单元格等操作都是在函数“Sections”及其子函数中完成
<xsl:call-template name="Sections"/>
7. [b]ss:MergeAcross[/b]是Cell的属性, 用于单元格的横向合并
下面的例子表示:合并当前单元格右边的4个单元格(即横向区域总共5个单元格被合并)
<Cell ss:MergeAcross="4" ss:StyleID="s121">
8. [b]ss:MergeDown[/b]是Cell的属性, 用于单元格的纵向合并
下面的例子表示:合并当前单元格下边的4个单元格(即纵向区域总共5个单元格被合并)
<Cell ss:MergeDown="4" ss:StyleID="s121">
[b] 以上即是关键部分,原本想就后面的函数多解释解释,但想来是没大必要的,不仅仅是简单的缘故,相信大家都是牛**的developer,所以解释的太多反倒不美。所以就此打住,刚接触xslt的同学参考例子多思考思考,多写写就可以了[/b]