刚接手的项目有一查询页面,客户要求的实现格式较为复杂,需要达到合并多行多列的显示效果,由于只是一个小项目,客户方面不愿意引入太多外部的商业控件, 剩下的解决方案无外乎是:1.使用DataGrid; 2.使用SQL Reporting Services;3.自己合成html代码输出。

在 这些解决方案中,使用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">&nbsp;</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">&nbsp;</td>                
        
<td class="sizebar">&nbsp;</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">&nbsp;</td>                
        
<td align="right">26</td>
    
</tr>                        
</table>
要达到输出如此效果的HTML,而又不是在代码处进行硬编码,实现数据和页面输出的分离,XSL和XML结合自然就是不二之选了。通过从数据库中查询得到的结果集合生成指定格式的xml,然后通过预先写好的XSL结合,就可实现需要的效果。

之前并未接触太多的XSL方面的知识,只是有一个初步的理解,实际操作起来方知XSL这款所谓的“编程”语言,对于习惯既有编程语言模式的程序员而言可谓“噩梦”,很多的处理方法颠覆了既有的处理方法,有赖于强大的Google搜索引擎,方能勉强实现所要效果.

附件(下载)中的例子使用Vs.net 2003,只是一个简单的实现。XSL并不熟悉,写得较为凌乱,欢迎讨论。实现的效果可以参考下面的图:


附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 &gt; 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 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
posted on 2007-05-29 16:24  Dragon-China  阅读(2099)  评论(1编辑  收藏  举报