在 这些解决方案中,使用DataGrid的话,要达到合并行和列比较麻烦;而Reporting Services合并行和列相对简单,但因为显示结果的列数是动态的,这无论是写SQL和制作Reporting Services的rdl文件都是相当复杂的事。于是惟有通过生成自定义html代码的解决方法了。
在HTML代码中,要实现table元素的表和列合并主要是使用rowspan 和 colspan属性,比如要实现下面的格式输出,
服装 | 颜色 | 码组 | 总数量 | |||||
衬衫 | S | M | L | XL | XXL | |||
白 | 7 | 10 | 2 | 3 | 4 | 26 |
可采用以下的HTML代码:
<
table
cellSpacing
="0"
cellPadding
="0"
border
="1"
bordercolor
="black"
style
="border-collapse:collapse"
>
< tr align ="center" class ="titlebar" >
< td width ="120" > 服装 </ td >
< td width ="50" > 颜色 </ td >
< td colspan ="6" > 码组 </ td >
< td width ="50" > 总数量 </ td >
</ tr >
< tr align ="center" >
< td rowspan ="2" > 衬衫 </ td >
< td class ="sizebar" > </ td >
< td width ="40" class ="sizebar" > S </ td >
< td width ="40" class ="sizebar" > M </ td >
< td width ="40" class ="sizebar" > L </ td >
< td width ="40" class ="sizebar" > XL </ td >
< td width ="40" class ="sizebar" > XXL </ td >
< td width ="40" class ="sizebar" > </ td >
< td class ="sizebar" > </ td >
</ tr >
< tr >
< td align ="center" > 白 </ td >
< td align ="right" > 7 </ td >
< td align ="right" > 10 </ td >
< td align ="right" > 2 </ td >
< td align ="right" > 3 </ td >
< td align ="right" > 4 </ td >
< td align ="right" > </ td >
< td align ="right" > 26 </ td >
</ tr >
</ table >
要达到输出如此效果的HTML,而又不是在代码处进行硬编码,实现数据和页面输出的分离,XSL和XML结合自然就是不二之选了。通过从数据库中查询得到的结果集合生成指定格式的xml,然后通过预先写好的XSL结合,就可实现需要的效果。
< tr align ="center" class ="titlebar" >
< td width ="120" > 服装 </ td >
< td width ="50" > 颜色 </ td >
< td colspan ="6" > 码组 </ td >
< td width ="50" > 总数量 </ td >
</ tr >
< tr align ="center" >
< td rowspan ="2" > 衬衫 </ td >
< td class ="sizebar" > </ td >
< td width ="40" class ="sizebar" > S </ td >
< td width ="40" class ="sizebar" > M </ td >
< td width ="40" class ="sizebar" > L </ td >
< td width ="40" class ="sizebar" > XL </ td >
< td width ="40" class ="sizebar" > XXL </ td >
< td width ="40" class ="sizebar" > </ td >
< td class ="sizebar" > </ td >
</ tr >
< tr >
< td align ="center" > 白 </ td >
< td align ="right" > 7 </ td >
< td align ="right" > 10 </ td >
< td align ="right" > 2 </ td >
< td align ="right" > 3 </ td >
< td align ="right" > 4 </ td >
< td align ="right" > </ td >
< td align ="right" > 26 </ td >
</ tr >
</ table >
之前并未接触太多的XSL方面的知识,只是有一个初步的理解,实际操作起来方知XSL这款所谓的“编程”语言,对于习惯既有编程语言模式的程序员而言可谓“噩梦”,很多的处理方法颠覆了既有的处理方法,有赖于强大的Google搜索引擎,方能勉强实现所要效果.
附件( 下载)中的例子使用Vs.net 2003,只是一个简单的实现。XSL并不熟悉,写得较为凌乱,欢迎讨论。实现的效果可以参考下面的图:
附XSL文件
WarehouseLayout.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:variable name="SizeColWidth" select="40" />
<xsl:template match="/Warehouse">
<!-- Get the maxium in Size Columns -->
<xsl:for-each select="Item/Color">
<xsl:sort select="count(Size)" order="descending"/>
<xsl:if test="position() = 1"> <!-- Only the first one will be executed -->
<xsl:call-template name="show_table">
<xsl:with-param name="maxSizeCols" select="count(Size)" />
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="show_table">
<xsl:param name="maxSizeCols" />
<table cellSpacing="0" cellPadding="0" border="1" bordercolor="black" style="border-collapse:collapse">
<tr align="center" class="titlebar">
<td width="120">服装</td>
<td width="50">颜色</td>
<td colspan="{$maxSizeCols}">码组</td>
<td width="50">总数量</td>
</tr>
<xsl:for-each select="../../Item">
<xsl:if test="@name != ''">
<xsl:variable name="colorCount" select="count(Color) + 1" />
<tr align="center">
<td rowspan="{$colorCount}"><xsl:value-of select="@name"></xsl:value-of></td> <!-- 服装列 -->
<td class="sizebar"></td> <!-- 颜色表头列 -->
<!-- 生成尺码表头列,不足的以空列补充 -->
<xsl:for-each select="Color">
<xsl:sort select="count(Size)" order="descending"/>
<xsl:if test="position() = 1">
<xsl:for-each select="Size">
<td width="{$SizeColWidth}" class="sizebar"><xsl:value-of select="@name"></xsl:value-of></td>
</xsl:for-each>
<xsl:call-template name="InsertBlankTD">
<xsl:with-param name="counter" select="$maxSizeCols - count(Size)" />
<xsl:with-param name="tdclass" select="'sizebar'" />
</xsl:call-template>
</xsl:if>
</xsl:for-each>
<td class="sizebar"></td> <!-- 总数量表头列 -->
<xsl:for-each select="Color">
<tr>
<td align="center"><xsl:value-of select="@name"></xsl:value-of></td>
<xsl:for-each select="Size">
<td align="right"><xsl:value-of select="text()"></xsl:value-of></td>
</xsl:for-each>
<xsl:call-template name="InsertBlankTD">
<xsl:with-param name="counter" select="$maxSizeCols - count(Size)" />
<xsl:with-param name="tdclass" select="''" />
</xsl:call-template>
<td align="right"><xsl:value-of select="@total"></xsl:value-of></td>
</tr>
</xsl:for-each>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="InsertBlankTD">
<xsl:param name="counter" />
<xsl:param name="tdclass" /> <!-- blank for no class-->
<xsl:if test="$counter > 0">
<xsl:choose>
<xsl:when test="$tdclass = ''">
<td />
</xsl:when>
<xsl:otherwise>
<td width="{$SizeColWidth}" class="{$tdclass}" />
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="InsertBlankTD">
<xsl:with-param name="counter" select="$counter - 1" />
<xsl:with-param name="tdclass" select="$tdclass" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:variable name="SizeColWidth" select="40" />
<xsl:template match="/Warehouse">
<!-- Get the maxium in Size Columns -->
<xsl:for-each select="Item/Color">
<xsl:sort select="count(Size)" order="descending"/>
<xsl:if test="position() = 1"> <!-- Only the first one will be executed -->
<xsl:call-template name="show_table">
<xsl:with-param name="maxSizeCols" select="count(Size)" />
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="show_table">
<xsl:param name="maxSizeCols" />
<table cellSpacing="0" cellPadding="0" border="1" bordercolor="black" style="border-collapse:collapse">
<tr align="center" class="titlebar">
<td width="120">服装</td>
<td width="50">颜色</td>
<td colspan="{$maxSizeCols}">码组</td>
<td width="50">总数量</td>
</tr>
<xsl:for-each select="../../Item">
<xsl:if test="@name != ''">
<xsl:variable name="colorCount" select="count(Color) + 1" />
<tr align="center">
<td rowspan="{$colorCount}"><xsl:value-of select="@name"></xsl:value-of></td> <!-- 服装列 -->
<td class="sizebar"></td> <!-- 颜色表头列 -->
<!-- 生成尺码表头列,不足的以空列补充 -->
<xsl:for-each select="Color">
<xsl:sort select="count(Size)" order="descending"/>
<xsl:if test="position() = 1">
<xsl:for-each select="Size">
<td width="{$SizeColWidth}" class="sizebar"><xsl:value-of select="@name"></xsl:value-of></td>
</xsl:for-each>
<xsl:call-template name="InsertBlankTD">
<xsl:with-param name="counter" select="$maxSizeCols - count(Size)" />
<xsl:with-param name="tdclass" select="'sizebar'" />
</xsl:call-template>
</xsl:if>
</xsl:for-each>
<td class="sizebar"></td> <!-- 总数量表头列 -->
<xsl:for-each select="Color">
<tr>
<td align="center"><xsl:value-of select="@name"></xsl:value-of></td>
<xsl:for-each select="Size">
<td align="right"><xsl:value-of select="text()"></xsl:value-of></td>
</xsl:for-each>
<xsl:call-template name="InsertBlankTD">
<xsl:with-param name="counter" select="$maxSizeCols - count(Size)" />
<xsl:with-param name="tdclass" select="''" />
</xsl:call-template>
<td align="right"><xsl:value-of select="@total"></xsl:value-of></td>
</tr>
</xsl:for-each>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="InsertBlankTD">
<xsl:param name="counter" />
<xsl:param name="tdclass" /> <!-- blank for no class-->
<xsl:if test="$counter > 0">
<xsl:choose>
<xsl:when test="$tdclass = ''">
<td />
</xsl:when>
<xsl:otherwise>
<td width="{$SizeColWidth}" class="{$tdclass}" />
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="InsertBlankTD">
<xsl:with-param name="counter" select="$counter - 1" />
<xsl:with-param name="tdclass" select="$tdclass" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
示例XMLl文件
XML Sample
<?xml version="1.0" encoding="UTF-8"?>
<Warehouse>
<Item name="西服">
<Color name="黑" total="24">
<Size name="S">5</Size>
<Size name="M">4</Size>
<Size name="L">7</Size>
<Size name="XL">8</Size>
</Color>
<Color name="灰" total="10">
<Size name="S">5</Size>
<Size name="M">1</Size>
<Size name="L">4</Size>
<Size name="XL"/>
</Color>
</Item>
<Item name="衬衫">
<Color name="白" total="16">
<Size name="38">7</Size>
<Size name="39"></Size>
<Size name="40">2</Size>
<Size name="41">3</Size>
<Size name="42">4</Size>
</Color>
</Item>
<Item name="皮鞋">
<Color name="黑" total="15">
<Size name="7">1</Size>
<Size name="8">5</Size>
<Size name="9">5</Size>
<Size name="10">4</Size>
<Size name="11"/>
<Size name="12"/>
</Color>
<Color name="灰" total="13">
<Size name="7"/>
<Size name="8"/>
<Size name="9">5</Size>
<Size name="10">3</Size>
<Size name="11"/>
<Size name="12">5</Size>
</Color>
</Item>
</Warehouse>
<?xml version="1.0" encoding="UTF-8"?>
<Warehouse>
<Item name="西服">
<Color name="黑" total="24">
<Size name="S">5</Size>
<Size name="M">4</Size>
<Size name="L">7</Size>
<Size name="XL">8</Size>
</Color>
<Color name="灰" total="10">
<Size name="S">5</Size>
<Size name="M">1</Size>
<Size name="L">4</Size>
<Size name="XL"/>
</Color>
</Item>
<Item name="衬衫">
<Color name="白" total="16">
<Size name="38">7</Size>
<Size name="39"></Size>
<Size name="40">2</Size>
<Size name="41">3</Size>
<Size name="42">4</Size>
</Color>
</Item>
<Item name="皮鞋">
<Color name="黑" total="15">
<Size name="7">1</Size>
<Size name="8">5</Size>
<Size name="9">5</Size>
<Size name="10">4</Size>
<Size name="11"/>
<Size name="12"/>
</Color>
<Color name="灰" total="13">
<Size name="7"/>
<Size name="8"/>
<Size name="9">5</Size>
<Size name="10">3</Size>
<Size name="11"/>
<Size name="12">5</Size>
</Color>
</Item>
</Warehouse>
转自:http://www.cnblogs.com/yeti/archive/2007/03/08/667117.html