如何把xml文件轉換成vml圖形

如何把xml文件轉換成vml圖形

摘要:在很多情況下,我們需要把數據轉換成圖表的形式來顯示。一直有個想法兒就是數據用xml來表示,這個xml文件可以用asp或者asp.net在服務器端提取數據庫並拼接而成。然後寫個通用的xslt文件把這些xml文件轉換成柱形,餅形,曲線形等圖形報表。因爲這裏面涉及好多xslt和css高級的東西,比如說xslt的遞歸處理,和css的表達式等,所以做這個東西的時候很費力,而且到最後還有一些遺憾的地方。本示例沒有用xslt和javascript交互的地方,下次改進的時候如果能利用好javascript的靈活性和麪向對象特性的話,以及xslt的一些高級的內容的話,我想這次遺留下的問題應該會解決的,也許我們還可以不把它們進一步封裝成自定義服務器控件,以達到重用的效果。

首先要說的是,利用VML做圖表,我肯定不是第一個,james用js寫的vmlchart組件,還有網上流行的三個用asp輸出的特漂亮的圖表,這些例子都很好,不過我用的時候感覺靈活性還是不太好,於是我纔想好好研究研究。因爲用vml做圖表有很多的優勢,以前我和羣裏的朋友討論過這個問題。下面是我當時的一些隨筆。

報表裏一般都有生成自定義圖表的功能,OWC是不錯的選擇,微軟提供的免費組件,可是如果用在WEB上性能是個問題,如果訪問量大的話,每個訪問都會實例化一次OWC對象,非常消耗資源,如果用居網內的信息系統還可以考慮,其它ACTIVEX圖表組件應該也有這個缺陷吧,我想一個可行的辦法就是調用客戶端的OWC來生成圖表,然後利用遠程XML或者WEB服務來作爲數據源,可是這樣如果是WEB系統的話,OWC的分發部署還是個問題,有些人的瀏覽器默認禁止下載ACTIVEX,對於一個有廣大訪問者的網站,強制用戶下載某個組件我感覺不是很好吧。水晶報表的性能據說已經優化非常好了,能經得住很高的訪問流量,sqlserver reporting serivice是一套web serivice,可以跨平臺,我看過微軟的培訓錄像,功能也很強大,能生成各種格式,但是還得建立專門的報表服務器,也很麻煩,如果有一套vml或者svg的圖表類庫就好了,可以在客戶端顯示豐富的圖表,而不用下載插件,也不用損耗服務器性能,不行去國外的開源網站逛逛,看看有沒有好看的,現成的,功能強大的VML chart,呵呵。

先來看我們準備的原始xml文件,是一個投票系統的元數據,因爲民意調查一般都是用柱形圖顯示的,所以就用這個來做示例,而且引起我對VML感興趣的原因之一也是我想用VML做一個顯示調查結果的念頭。
vote.xml

<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="Vmlchart.xslt"?>
<votelist>
  
<vote type="rect" desc="你喜歡哪個語言?">
    
<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>

然後我們來看樣式表,這個樣式表是我昨天下午早就寫好了的,經過一上午的研究,基本上沒有做什麼改進,哎。本來呢,我想讓它轉換出來的圖形更加專業一些,我想給圖形加上X座標和Y座標,再在每個圖形的上面顯示它們各自代表的條目,以及佔總投票數的百分比之類的信息,可惜我讓它顯示條目名稱的時候整個圖表的寬度加大了,而且每個柱形的間距也加大了,我當時是用的vml的textbox和css的絕對定位來做的條目名稱顯示。如果把position設置成absolute 所有的名稱都會重疊在一起,如果設置成relative,柱形圖的間距就會加大,因爲每個柱形之間加了textbox的位置,隨意被撐開了,然後呢我想設置成absolute,然後根據循環的次數來讓textbox的left屬性每次加50象素,讓它正好位於自己條形圖的上方。可是弄了一上午,用xsl:param,xsl:with-param,xsl:variable弄了好半天也沒弄出來,xsl:variable一經聲明值就不能變了,隨意不能在循環的時候更新它的值,而xsl:param只能在xsl:call-template裏面修改它的值,而且xsl:call-template裏用xsl:with-param修改param的值的時候還得必須應用xsl:param聲明的模板,否則param的作用域打不到那裏,所以只能用遞歸來模擬這種循環增加值的效果,這就需要一個全局變量來控制xsl:if的條件,在解析完item元素後停止讓left+50,可是這個全局變量的值怎麼也變不了,我弄了好幾次,都提示遞歸太深,造成解析死循環,我暈的,想不到這XSLT簡直不是一般的複雜,不知道以後的XAML會複雜到何等程度,我快瘋了,就帶着遺憾先把這個效果做完吧。
VmlChart.xslt

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl
="http://www.w3.org/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>調查:
        
<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>

到現在我們打開第一步建立的vote.xml就可以看到,它已經成功的轉換成了圖形,是不是有些效果了呀,呵呵。其實還可以用css濾境讓條形圖做一些漸變色,透明處理等效果,讓它更好看,我在下載的代碼裏提供了幾個靜態的vml圖表,大家可以預覽一下這個效果。文件名叫vmlchart.htm。單純瀏覽xml文件,它會只顯示個圖表,而往往圖表應該穿插在一段文字之間,我們一般在html文件中想要呈現圖表的地方讓它顯示,下面我們做了一個html文件,來演示這個過程。
Chart.htm

<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> 

上面的代碼,看不懂,不要着急,我最後會給大家提供一些我在昨天和今天看的一些文章和資料的地址,裏面有豐富的關於我在做這個演示中解決各種問題的答案,我就不在畫蛇添足,狗尾續貂的加那麼多註釋了,以前我就愛貼代碼,有人便提醒我,把思路說說就行了,別人沒空看你那些代碼的,所以呢我現在就着重貼關鍵重要的代碼,把完整代碼以附件的形式提供給大家下載。
最後呢,因爲目前我所展示給大家的和.NET一點兒關係也沒有,而且好幾次我發這樣類似的文章到首頁都被T了回來,原因是和.NET無關,所以呢,我得再寫個.NET的例子,以便和.NET沾上邊兒,好放到首頁上來。下面是代碼。
Default.aspx

 

<%@ 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吧,不過感覺.NET裏關於XML處理的有好幾個類特別有意思,比用腳本處理xml有趣多了。

改進:希望看到此POST的XML高手把偶的例子修改一下,以便讓每個條形的上面顯示它的投票數和佔總投票數的比例,想做到這個我是一點兒思路也沒有了,然後呢如果解決了這個問題的話,我想把它封裝成一個htc的可重用組件,然後呢,進一步弄成.NET 自定義控件。

小節:有關XML的技術簡直是數不勝數,而且應用也越來越廣,想做好一個程序員,在知識上必須要有一定的深度和廣度,XML無所不在,而且前途廣大,隨意還是從現在開始深入研究它吧。

腳註:下面提供一些我找的一些鏈接
Fusionner deux fichiers XML en XSLT
http://developpeur.journaldunet.com/ressource/xml/xml_merge.shtml

使用XSLT參數控制轉換
http://www.zdnet.com.cn/developer/common/printfriend/printfriendly.htm?AT=39310562-3800066897t-20000560c

周未XSLT培訓資料!
http://edobnet.cnblogs.com/archive/2004/06/21/17437.html

javascript如何控制xsl:param參數值?
http://forum.opendl.com/viewtopic.php?t=211&sid=cc8420a8ad950340828e03a0fc1c276a

XPath+XSLT
http://blog.joycode.com/saucer/archive/2004/08/02/29299.aspx

XML有問必答
http://forum.opendl.com/viewforum.php?f=5

IBM XML
http://www-128.ibm.com/developerworks/cn/xml/

技巧:將 XSLT 查找表打包成 EXSLT 函數
http://www-128.ibm.com/developerworks/cn/xml/x-tiplook2.html?ca=dwcn-newsletter-xml

XSLT知識總結
http://www.21ds.net/article/_3/_9/2005-05/28/567_1.html


發賽特技術網XSLT專題
http://www.ftponline.com/china/class.aspx?sort=XSLT

XSLT中的循環
http://bbs.xml.org.cn/dispbbs.asp?boardID=8&ID=12106

源碼下載地址:http://files.cnblogs.com/onlytiancai/TestVml.rar

 

發佈了98 篇原創文章 · 獲贊 2 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章