|
摘要:在很多情況下,我們需要把數(shù)據(jù)轉(zhuǎn)換成圖表的形式來(lái)顯示。一直有個(gè)想法兒就是數(shù)據(jù)用xml來(lái)表示,這個(gè)xml文件可以用asp或者asp.net在服務(wù)器端提取數(shù)據(jù)庫(kù)并拼接而成。然后寫(xiě)個(gè)通用的xslt文件把這些xml文件轉(zhuǎn)換成柱形,餅形,曲線形等圖形報(bào)表。因?yàn)檫@里面涉及好多xslt和css高級(jí)的東西,比如說(shuō)xslt的遞歸處理,和css的表達(dá)式等,所以做這個(gè)東西的時(shí)候很費(fèi)力,而且到最后還有一些遺憾的地方。本示例沒(méi)有用xslt和javascript交互的地方,下次改進(jìn)的時(shí)候如果能利用好javascript的靈活性和面向?qū)ο筇匦缘脑?,以及xslt的一些高級(jí)的內(nèi)容的話,我想這次遺留下的問(wèn)題應(yīng)該會(huì)解決的,也許我們還可以不把它們進(jìn)一步封裝成自定義服務(wù)器控件,以達(dá)到重用的效果。 首先要說(shuō)的是,利用VML做圖表,我肯定不是第一個(gè),james用js寫(xiě)的vmlchart組件,還有網(wǎng)上流行的三個(gè)用asp輸出的特漂亮的圖表,這些例子都很好,不過(guò)我用的時(shí)候感覺(jué)靈活性還是不太好,于是我才想好好研究研究。因?yàn)橛胿ml做圖表有很多的優(yōu)勢(shì),以前我和群里的朋友討論過(guò)這個(gè)問(wèn)題。下面是我當(dāng)時(shí)的一些隨筆。 報(bào)表里一般都有生成自定義圖表的功能,OWC是不錯(cuò)的選擇,微軟提供的免費(fèi)組件,可是如果用在WEB上性能是個(gè)問(wèn)題,如果訪問(wèn)量大的話,每個(gè)訪問(wèn)都會(huì)實(shí)例化一次OWC對(duì)象,非常消耗資源,如果用居網(wǎng)內(nèi)的信息系統(tǒng)還可以考慮,其它ACTIVEX圖表組件應(yīng)該也有這個(gè)缺陷吧,我想一個(gè)可行的辦法就是調(diào)用客戶端的OWC來(lái)生成圖表,然后利用遠(yuǎn)程XML或者WEB服務(wù)來(lái)作為數(shù)據(jù)源,可是這樣如果是WEB系統(tǒng)的話,OWC的分發(fā)部署還是個(gè)問(wèn)題,有些人的瀏覽器默認(rèn)禁止下載ACTIVEX,對(duì)于一個(gè)有廣大訪問(wèn)者的網(wǎng)站,強(qiáng)制用戶下載某個(gè)組件我感覺(jué)不是很好吧。水晶報(bào)表的性能據(jù)說(shuō)已經(jīng)優(yōu)化非常好了,能經(jīng)得住很高的訪問(wèn)流量,sqlserver reporting serivice是一套web serivice,可以跨平臺(tái),我看過(guò)微軟的培訓(xùn)錄像,功能也很強(qiáng)大,能生成各種格式,但是還得建立專門(mén)的報(bào)表服務(wù)器,也很麻煩,如果有一套vml或者svg的圖表類庫(kù)就好了,可以在客戶端顯示豐富的圖表,而不用下載插件,也不用損耗服務(wù)器性能,不行去國(guó)外的開(kāi)源網(wǎng)站逛逛,看看有沒(méi)有好看的,現(xiàn)成的,功能強(qiáng)大的VML chart,呵呵。 先來(lái)看我們準(zhǔn)備的原始xml文件,是一個(gè)投票系統(tǒng)的元數(shù)據(jù),因?yàn)槊褚庹{(diào)查一般都是用柱形圖顯示的,所以就用這個(gè)來(lái)做示例,而且引起我對(duì)VML感興趣的原因之一也是我想用VML做一個(gè)顯示調(diào)查結(jié)果的念頭。 <?xml version="1.0" encoding="utf-8" ?> <?xml-stylesheet type="text/xsl" href="Vmlchart.xslt"?> <votelist> <vote type="rect" desc="你喜歡哪個(gè)語(yǔ)言?"> <item name="asp.net" color="red">100</item> <item name="c#" color="aqua">20</item> <item name="asp" color="blue">60</item> <item name="vb.net" color="gray">25</item> <item name="delphi" color="green">72</item> <item name="java" color="lime">62</item> <item name="python" color="maroon">29</item> <item name="c++" color="navy">55</item> <item name="php" color="olive">18</item> </vote> </votelist>![]() 然后我們來(lái)看樣式表,這個(gè)樣式表是我昨天下午早就寫(xiě)好了的,經(jīng)過(guò)一上午的研究,基本上沒(méi)有做什么改進(jìn),哎。本來(lái)呢,我想讓它轉(zhuǎn)換出來(lái)的圖形更加專業(yè)一些,我想給圖形加上X坐標(biāo)和Y坐標(biāo),再在每個(gè)圖形的上面顯示它們各自代表的條目,以及占總投票數(shù)的百分比之類的信息,可惜我讓它顯示條目名稱的時(shí)候整個(gè)圖表的寬度加大了,而且每個(gè)柱形的間距也加大了,我當(dāng)時(shí)是用的vml的textbox和css的絕對(duì)定位來(lái)做的條目名稱顯示。如果把position設(shè)置成absolute 所有的名稱都會(huì)重疊在一起,如果設(shè)置成relative,柱形圖的間距就會(huì)加大,因?yàn)槊總€(gè)柱形之間加了textbox的位置,隨意被撐開(kāi)了,然后呢我想設(shè)置成absolute,然后根據(jù)循環(huán)的次數(shù)來(lái)讓textbox的left屬性每次加50象素,讓它正好位于自己條形圖的上方??墒桥艘簧衔纾脁sl:param,xsl:with-param,xsl:variable弄了好半天也沒(méi)弄出來(lái),xsl:variable一經(jīng)聲明值就不能變了,隨意不能在循環(huán)的時(shí)候更新它的值,而xsl:param只能在xsl:call-template里面修改它的值,而且xsl:call-template里用xsl:with-param修改param的值的時(shí)候還得必須應(yīng)用xsl:param聲明的模板,否則param的作用域打不到那里,所以只能用遞歸來(lái)模擬這種循環(huán)增加值的效果,這就需要一個(gè)全局變量來(lái)控制xsl:if的條件,在解析完item元素后停止讓left+50,可是這個(gè)全局變量的值怎么也變不了,我弄了好幾次,都提示遞歸太深,造成解析死循環(huán),我暈的,想不到這XSLT簡(jiǎn)直不是一般的復(fù)雜,不知道以后的XAML會(huì)復(fù)雜到何等程度,我快瘋了,就帶著遺憾先把這個(gè)效果做完吧。 <?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www./1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:v="urn:schemas-microsoft-com:vml"> <xsl:template match="/"> <HTML> <HEAD> <STYLE>v\:*{behavior:url(#default#VML);}</STYLE> <TITLE>蛙蛙池塘圖表</TITLE> </HEAD> <BODY> <xsl:apply-templates select="votelist" /> </BODY> </HTML> </xsl:template> <xsl:template match="votelist" name="votelist"> <xsl:for-each select="vote"> <div style="POSITION:absolute ;Z-INDEX:3;LEFT:110px;TOP:10px;font-size:14px;"> <b>調(diào)查: <xsl:value-of select="@desc"/> </b> </div> <xsl:for-each select="item"> <v:rect style="POSITION:relative ;Z-INDEX:3;LEFT:100px;TOP:25px;width:20;height:{.};" fillcolor="{@color}" stroked="f"> </v:rect> </xsl:for-each> <table style="POSITION:absolute ;Z-INDEX:3;LEFT:110px;TOP:145px;border:1px solid #f1f1f1;font-size:12px;"> <xsl:for-each select="item"> <tr> <td> <v:rect style="Z-INDEX:3;width:15;height:15;" fillcolor="{@color}" stroked="f"> </v:rect> <xsl:value-of select="."/> </td> <td> <xsl:value-of select="@name"/> </td> </tr> </xsl:for-each> </table> </xsl:for-each> </xsl:template> </xsl:stylesheet>![]() 到現(xiàn)在我們打開(kāi)第一步建立的vote.xml就可以看到,它已經(jīng)成功的轉(zhuǎn)換成了圖形,是不是有些效果了呀,呵呵。其實(shí)還可以用css濾境讓條形圖做一些漸變色,透明處理等效果,讓它更好看,我在下載的代碼里提供了幾個(gè)靜態(tài)的vml圖表,大家可以預(yù)覽一下這個(gè)效果。文件名叫vmlchart.htm。單純?yōu)g覽xml文件,它會(huì)只顯示個(gè)圖表,而往往圖表應(yīng)該穿插在一段文字之間,我們一般在html文件中想要呈現(xiàn)圖表的地方讓它顯示,下面我們做了一個(gè)html文件,來(lái)演示這個(gè)過(guò)程。 <HTML xmlns:v="urn:schemas-microsoft-com:vml"> <HEAD> ![]() <STYLE> v\:*{ }{behavior:url(#default#VML);}</STYLE>![]() <SCRIPT language="jscript"> var objSrcTree, ObjXSLT, objCache; function init() ![]() { objSrcTree = new ActiveXObject(‘MSXML2.DOMDocument.4.0‘); objSrcTree.async = false; objSrcTree.load(‘vote.xml‘); ![]() objXSLT=new ActiveXObject(‘MSXML2.FreeThreadedDOMDocument.4.0‘); objXSLT.async = false; objXSLT.load(‘VmlChart.xslt‘); ![]() objCache = new ActiveXObject("Msxml2.XSLTemplate.4.0"); objCache.stylesheet = objXSLT; } function show(title) ![]() { var objXSLTProc = objCache.createProcessor(); objXSLTProc.input = objSrcTree; objXSLTProc.transform(); output.innerHTML = objXSLTProc.output; } ![]() </SCRIPT> </HEAD> ![]() <BODY onload="init();show(‘TITLE‘);"> <DIV id="output" <div style="POSITION:absolute ;Z-INDEX:3;LEFT:250px;TOP:100px;"></DIV> </BODY> </HTML> ![]() ![]() 上面的代碼,看不懂,不要著急,我最后會(huì)給大家提供一些我在昨天和今天看的一些文章和資料的地址,里面有豐富的關(guān)于我在做這個(gè)演示中解決各種問(wèn)題的答案,我就不在畫(huà)蛇添足,狗尾續(xù)貂的加那么多注釋了,以前我就愛(ài)貼代碼,有人便提醒我,把思路說(shuō)說(shuō)就行了,別人沒(méi)空看你那些代碼的,所以呢我現(xiàn)在就著重貼關(guān)鍵重要的代碼,把完整代碼以附件的形式提供給大家下載。 ![]() <% @ Page Language="C#" %>![]() <% @ Import Namespace="System.Xml" %>![]() <% @ Import Namespace="System.Xml.XPath" %>![]() <% @ Import Namespace="System.Xml.Xsl" %>![]() <script runat="server">![]() private const String filename = "vote.xml"; private const String stylesheet = "VmlChart.xslt";![]() private void Page_Load(object sender, System.EventArgs e)![]() { if (!IsPostBack)![]() { XslTransform xslt = new XslTransform(); xslt.Load(Server.MapPath(stylesheet)); XPathDocument xpathdocument = new XPathDocument( Server.MapPath(filename)); XmlTextWriter writer = new XmlTextWriter(Response.Output); writer.Formatting = Formatting.Indented;![]() xslt.Transform(xpathdocument, null, writer, null); } }![]() </script>![]() ![]() 上面的代碼我也不多解釋了,都是在MSDN里抄的,有興趣看看MSDN吧,不過(guò)感覺(jué).NET里關(guān)于XML處理的有好幾個(gè)類特別有意思,比用腳本處理xml有趣多了。 改進(jìn):希望看到此POST的XML高手把偶的例子修改一下,以便讓每個(gè)條形的上面顯示它的投票數(shù)和占總投票數(shù)的比例,想做到這個(gè)我是一點(diǎn)兒思路也沒(méi)有了,然后呢如果解決了這個(gè)問(wèn)題的話,我想把它封裝成一個(gè)htc的可重用組件,然后呢,進(jìn)一步弄成.NET 自定義控件。 小節(jié):有關(guān)XML的技術(shù)簡(jiǎn)直是數(shù)不勝數(shù),而且應(yīng)用也越來(lái)越廣,想做好一個(gè)程序員,在知識(shí)上必須要有一定的深度和廣度,XML無(wú)所不在,而且前途廣大,隨意還是從現(xiàn)在開(kāi)始深入研究它吧。 腳注:下面提供一些我找的一些鏈接 使用XSLT參數(shù)控制轉(zhuǎn)換 周未XSLT培訓(xùn)資料! javascript如何控制xsl:param參數(shù)值? XPath+XSLT XML有問(wèn)必答 IBM XML 技巧:將 XSLT 查找表打包成 EXSLT 函數(shù) XSLT知識(shí)總結(jié)
XSLT中的循環(huán) 源碼下載地址:http://www.cnblogs.com/Files/onlytiancai/TestVml.rar |
|
|