XML - 報表數(shù)據(jù)的新大陸
隨著B/S系統(tǒng)的普及和XML技術(shù)的深入應(yīng)用,越來越多的數(shù)據(jù)包裹著XML的外衣被存儲和扔來扔去。這些數(shù)據(jù)很多源自數(shù)據(jù)庫,但經(jīng)過一定的處理,數(shù)據(jù)更精簡,更貼近應(yīng)用。如果報表工具能利用這些XML數(shù)據(jù),則可以減少數(shù)據(jù)庫查詢和報表數(shù)據(jù)運(yùn)算操作,因為這些XML數(shù)據(jù)的始作俑者已經(jīng)完成了這些操作。因此說XML是報表數(shù)據(jù)的新大陸。
傳統(tǒng)的報表工具都是只能處理關(guān)系型數(shù)據(jù)庫,基本上不能處理其他數(shù)據(jù)。隨著時代的發(fā)展,一些報表工具加上了處理XML文檔的能力,但需要編程,編寫并配置插件,如此報表程序結(jié)構(gòu)復(fù)雜,接口眾多,用戶還需要根據(jù)各種規(guī)范動手編寫程序,若XML文檔格式有很多種,就需要編寫很多種的插件,報表開發(fā)量不小。
如果實現(xiàn)了一種能處理XML文檔,從中獲得報表數(shù)據(jù)的通用方法。則在定制報表模板的時候就教育報表引擎如何從XML文檔獲得數(shù)據(jù),則對于所有的或大部分的XML文檔無需編程,可減少報表開發(fā)量。
那么如何通用的處理具有復(fù)雜樹狀結(jié)構(gòu)的XML文檔呢?
大家知道,處理XML文檔有兩種模式,一個是DOM方式,另一個是流模式。DOM方式處理方便,但速度慢耗內(nèi)存,流模式處理速度快,省內(nèi)存但使用不方便。對于.NET平臺,使用System.Xml.XmlDocument對象來使用DOM方式處理XML文檔,而使用XmlReader 來使用流模式處理XML文檔。
W3C國際標(biāo)準(zhǔn)組織設(shè)計XML文檔的目標(biāo)是方便的存儲和交換小型數(shù)據(jù)包,而不考慮數(shù)據(jù)的冗余。因此若實際系統(tǒng)中出現(xiàn)巨大的XML文檔,則大多數(shù)情況下可以認(rèn)為是不恰當(dāng)?shù)氖褂肵ML技術(shù)。因此我認(rèn)為報表工具不應(yīng)當(dāng)處理巨大的XML文檔,在此前提下,為了實現(xiàn)方便,采用DOM方式來處理XML文檔。
在.NET中使用XmlDocument加載一個XML文檔后,會形成一個以XmlDocument為根節(jié)點的XML對象樹狀結(jié)構(gòu),面對這個XML樹結(jié)構(gòu),獲取其中的數(shù)據(jù)方法很自然的就是使用XPath技術(shù)了。XPath技術(shù)就是在XML樹狀結(jié)構(gòu)中,以某個節(jié)點作為起始節(jié)點,使用特定的描述表示的路徑移動到其他的節(jié)點,一般的是向其下層節(jié)點移動,比如移動到某個子節(jié)點或?qū)O節(jié)點,移動到某個屬性等等。
傳統(tǒng)的報表數(shù)據(jù)源模型是兩層的,即使擴(kuò)展到可以處理XML文檔也只能處理一次,既從根節(jié)點出發(fā),使用某個XPath 獲得字段的值。如此只能處理一次,處理完畢后XML就被扔掉了。但很多時候需要對XML文檔進(jìn)行進(jìn)一步處理。此時傳統(tǒng)的兩層報表數(shù)據(jù)源模型是不夠的。
為了能對XML文檔進(jìn)行精耕細(xì)作,需要從傳統(tǒng)的兩層數(shù)據(jù)源結(jié)構(gòu)突破到多層的報表數(shù)據(jù)源模型。在多層數(shù)據(jù)源節(jié)點中,每一個節(jié)點都映射到XML文檔中的某個節(jié)點,而它的子節(jié)點則使用XPath路徑映射到XML中的其他節(jié)點。如此遞歸循環(huán)后則多層的數(shù)據(jù)源可以映射到XML文檔中的任意節(jié)點。多層數(shù)據(jù)源模型實際上就是一個數(shù)據(jù)源樹,因此處理XML文檔也就是將兩顆樹在某些節(jié)點上釘在一起,而XPath就是釘子。因此需要注意各級數(shù)據(jù)源節(jié)點的XPath配置的連續(xù)性,若一個數(shù)據(jù)源節(jié)點的XPath設(shè)置不對,就像它釘錯了XML節(jié)點或者干脆釘在空處。則它本身和所有的子孫節(jié)點都都會綁定落空的。
在實際應(yīng)用中,由于XML文檔不是專門為報表而產(chǎn)生的,因此報表工具還可能要離開XML文檔來獲取更多的報表數(shù)據(jù),此時可能需要從XML文檔跳到其他XML文檔,或者返回數(shù)據(jù)庫繼續(xù)執(zhí)行SQL查詢。這就非??简瀳蟊頂?shù)據(jù)源模型的靈活性了。
大家都知道RSS文檔是一種XML文檔,在這里使用博客園的RSS文檔為例子說明從XML讀取報表數(shù)據(jù)的過程。首先考察一下RSS文檔的結(jié)構(gòu),博客園首頁的RSS文檔URL為 http://www.cnblogs.com/rss.aspx ,根節(jié)點為 rss , 然后有個 channel 子節(jié)點,下面包含了RSS文檔的基本信息,然后有若干個item節(jié)點,列出了所有文章的基本信息。item節(jié)點下面是文章的基本信息,其中 wfw:commentRss 子節(jié)點的內(nèi)容是針對該文章回帖信息RSS文檔的URL。可以根據(jù)這個URL加載的回帖信息RSS文檔,根據(jù)RSS文檔結(jié)構(gòu)可以定義出如下的報表數(shù)據(jù)源和RSS文檔的映射關(guān)系。

這里的RSSXML文檔有三層結(jié)構(gòu),而且需要動態(tài)加載XML文檔進(jìn)行更深入的處理,因此傳統(tǒng)的兩層結(jié)構(gòu)是肯定不夠的,必須采用多層次的報表數(shù)據(jù)源結(jié)構(gòu)。其過程是相當(dāng)復(fù)雜的,步驟為
- 加載 http://www.cnblogs.com/rss.aspx 處的XML文檔,作為主XML文檔,生成一個System.Xml.XmlDocument 對象,并以該XML文檔對象作為處理的出發(fā)點。
- 使用XPath"rss"遍歷所有符合該路徑的XML節(jié)點,很顯然只處理了一個節(jié)點,此時當(dāng)前位置就移動到rss節(jié)點。
- 從當(dāng)前節(jié)點處使用XPath"channel/title"獲得網(wǎng)站標(biāo)題,使用"channel/link"獲得網(wǎng)站地址,"channel/description"獲得網(wǎng)站說明,"channel/pubDate"獲得文檔發(fā)布時間。
- 從當(dāng)前節(jié)點處使用"channel"遍歷所有符合該路徑的XML節(jié)點,很顯然只處理了一個節(jié)點,此時當(dāng)前位置就移動到了"channel"節(jié)點。
- 變量當(dāng)前節(jié)點下的所有的item子節(jié)點,并依次設(shè)置為當(dāng)前節(jié)點。
- 從當(dāng)前節(jié)點處使用“title"獲得文章標(biāo)題,使用"link"獲得文章地址,使用”author"獲得作者,“pubDate"獲得發(fā)布時間,"description"獲得文章內(nèi)容,"slash:comment"獲得回復(fù)數(shù),“wfw:commentRss"獲得回復(fù)RSSXML文檔的URL。
- 當(dāng)處理"wfw:commentRss"節(jié)點時,程序根據(jù)某個特定的設(shè)置加載該節(jié)點數(shù)據(jù)指向的XML文檔,也就是加載針對當(dāng)前文章的回復(fù)RSSXML文檔。并遍歷剛剛加載的XML文檔的所有符合"rss/channel/item"的節(jié)點,并依次設(shè)置為當(dāng)前節(jié)點。
- 從當(dāng)前節(jié)點處,使用"author"獲得回復(fù)作者,使用”pubDate"獲得回復(fù)時間,使用"description"獲得回復(fù)內(nèi)容。
- 由于RSSXML文檔中的description節(jié)點處保存的時HTML代碼,因此還需要解析HTML代碼并提取其中的純文本內(nèi)容。
從上面的步驟可以看出,數(shù)據(jù)源結(jié)構(gòu)中的每一個節(jié)點都釘?shù)搅薠ML文檔中的某個節(jié)點,而且在回復(fù)列表這個節(jié)點中,程序執(zhí)行了XML文檔的跳轉(zhuǎn),從主XML文檔跳到回復(fù)RSSXML文檔,而且是處理樹狀結(jié)構(gòu)的,因此是遞歸操作,很多狀態(tài)信息都由系統(tǒng)調(diào)用堆棧自動保存,無需程序自己保存了。
如果報表程序能直接連接到博客園數(shù)據(jù)庫的話,還可以從文章作者這個節(jié)點執(zhí)行XML文檔到數(shù)據(jù)庫的跳轉(zhuǎn),直接查詢數(shù)據(jù)庫,獲得文章作者的一些注冊信息。實事上,這個數(shù)據(jù)源樹狀結(jié)構(gòu)中每一個節(jié)點都可以發(fā)生XML到XML,XML到數(shù)據(jù)庫,數(shù)據(jù)庫到XML的三種跳轉(zhuǎn),這大大擴(kuò)展了獲取報表數(shù)據(jù)的靈活性。
如果一個信息系統(tǒng)是純XML應(yīng)用的話,則報表工具就可以在眾多的XML文檔中跳躍著采集數(shù)據(jù)而不需要查詢數(shù)據(jù)庫,就像少林寺的武僧在梅花樁上打架而不用碰地,因此也就不用管下面是JAVA土壤的還是.NET土壤。此時所有的數(shù)據(jù)庫操作,業(yè)務(wù)邏輯等等都運(yùn)行在后臺,而報表工具無需關(guān)心,只要系統(tǒng)底層安全可靠,則報表模塊也就安全可靠,系統(tǒng)底層無論如何修改,只要XML文檔格式不變則報表模塊就不需要修改。對于非常復(fù)雜的報表數(shù)據(jù)源,超出了報表工具的定制能力,則可以編程提供一個XML文檔供報表程序使用。以前系統(tǒng)是直接通過API向報表程序提供復(fù)雜報表數(shù)據(jù),而現(xiàn)在通過XML文檔以“隔山打牛”的方式向報表程序提供復(fù)雜報表數(shù)據(jù)。此時系統(tǒng)結(jié)構(gòu)更安全,邊界更清楚,體現(xiàn)了XML WebService的指導(dǎo)思想。這種獲取數(shù)據(jù)的思想可以不局限于報表數(shù)據(jù)的獲取,還可以應(yīng)用到其他領(lǐng)域。
以上討論的應(yīng)用系統(tǒng)限于B/S系統(tǒng),但可以設(shè)想,C/S系統(tǒng)經(jīng)過改造,可以通過某種方式向報表工具提供XML數(shù)據(jù)文檔。
從上面的討論可以看出,XML確實是報表數(shù)據(jù)的新大陸,本人寫的報表工具已經(jīng)初步體現(xiàn)了這種思想。但這種思想可能有點激進(jìn),還不成熟不完善,希望大家多多指點。
XDesigner 軟件工作室 2006-8-30
posted on 2006-08-31 08:45 新型報表工具 xdesigner 閱讀(1470) 評論(3) 編輯 收藏 引用 收藏至365Key