摘 要: 基于XQuery查詢語(yǔ)言的XBRL查詢引擎首先借助JavaCC工具處理輸入的XQuery語(yǔ)句形成抽象語(yǔ)法樹,而后根據(jù)XQuery查詢特點(diǎn)編寫程序遍歷此語(yǔ)法樹來(lái)簡(jiǎn)化查詢語(yǔ)言的處理流程,降低查詢匹配的復(fù)雜度,提高查詢效率,利用“SAX+ DOM”方式解析XBRL文件并提取XQuery語(yǔ)句所查詢的數(shù)據(jù)信息。SAX方法可以提高查詢效率并節(jié)省內(nèi)存消耗,DOM方法可以支持對(duì)XBRL文件的上下文相關(guān)查詢及頻繁查詢。實(shí)驗(yàn)證明,將二者結(jié)合起來(lái)應(yīng)用滿足高查詢效率和低內(nèi)存消耗雙重需求。
關(guān)鍵詞: XBRL; XQuery; 解析器
XBRL[1](可擴(kuò)展商業(yè)報(bào)告語(yǔ)言)是XML語(yǔ)言的擴(kuò)展應(yīng)用,主要面向金融財(cái)政領(lǐng)域,對(duì)其進(jìn)行數(shù)據(jù)挖掘和分析具有重大意義,在實(shí)際項(xiàng)目中如何方便高效率地對(duì)其進(jìn)行數(shù)據(jù)提取并降低內(nèi)存消耗是需要解決的問(wèn)題。
W3C制定的XQuery語(yǔ)言中的FLOWR[2]可以高效率地對(duì)XBRL進(jìn)行查詢處理,目前國(guó)內(nèi)外有很多支持XQuery查詢語(yǔ)言的查詢引擎,如國(guó)外開源的XQEngine是一個(gè)基于JavaBean的用來(lái)查詢本地XML文檔的XQuery查詢引擎,該引擎使用SAX[3]解析方式來(lái)解析并提取XML中的所需信息,節(jié)省了內(nèi)存也保證了查詢速度。但是由于XBRL中的實(shí)例文件是承載財(cái)政數(shù)據(jù)的文件,其節(jié)點(diǎn)間存在密切的數(shù)據(jù)關(guān)聯(lián)關(guān)系,用戶多使用頻繁查詢及復(fù)合查詢等查詢實(shí)例文件進(jìn)行數(shù)據(jù)分析,“邊讀邊扔數(shù)據(jù)”的SAX方式無(wú)法滿足這一需求。本文提出的SAX+DOM方式可以解決這一問(wèn)題,同時(shí)在一定程度上比純DOM[4]讀取方式節(jié)省了大量?jī)?nèi)存。
圖1給出了基于XQuery的商業(yè)報(bào)告查詢引擎的整體框架,主要分為XQuery預(yù)處理模塊、查詢優(yōu)化器和查詢執(zhí)行器3個(gè)模塊。傳統(tǒng)的查詢優(yōu)化包括Schema模式優(yōu)化[5]、 XQuery語(yǔ)句查詢重寫、XML文檔索引技術(shù)、XQuery語(yǔ)句規(guī)范化等[6],而本文涉及的解析方式創(chuàng)新及抽象樹的遍歷簡(jiǎn)化則是從查詢引擎內(nèi)部實(shí)現(xiàn)角度對(duì)XQuery查詢進(jìn)行了優(yōu)化,下面著重對(duì)查詢引擎內(nèi)部?jī)?yōu)化中的XQuery預(yù)處理模塊及查詢執(zhí)行器進(jìn)行具體闡述。
1 遍歷Javacc生成的抽象語(yǔ)法樹
XQuery查詢語(yǔ)言被設(shè)計(jì)用來(lái)查詢XML(XBRL本質(zhì)上也為XML)文件,其語(yǔ)法中的FLWOR表達(dá)式是最重要的,它代表 For-Let-Where-Order by-Return。For子句通過(guò)將節(jié)點(diǎn)綁定到變量,以便繼續(xù)循環(huán)遍歷序列中的每一個(gè)節(jié)點(diǎn);let子句為一個(gè)變量賦一個(gè)值或一個(gè)序列;return 子句定義每個(gè)元組要返回的內(nèi)容;對(duì)于where子句,如果其有效布爾值為真,那么該元組就被保留,并且它的變量綁定用在return子句中,反之該元組就被廢棄[7]。
在查詢預(yù)處理模塊,通過(guò)JavaCC[8]工具和W3C已定義的XQuery語(yǔ)法規(guī)則來(lái)進(jìn)行詞法分析,將輸入的XQuery語(yǔ)句查詢語(yǔ)句中的每個(gè)成分都變成帶有特定屬性的節(jié)點(diǎn)并生成與之相對(duì)應(yīng)的類(例如顯示的是MainModule等,則語(yǔ)法解析時(shí)JavaCC中的JJtree以這些類為節(jié)點(diǎn)在內(nèi)存中生成樹形結(jié)構(gòu)),然后編寫程序遍歷抽象語(yǔ)法樹。下面的算法流程為遍歷FLOWR表達(dá)式中For語(yǔ)句對(duì)應(yīng)的抽象語(yǔ)法樹分支的流程,其中MainModule等均為使用JavaCC工具并根據(jù)W3C XQuery規(guī)范中XQuery BNF定義生成的語(yǔ)法樹中的抽象樹節(jié)點(diǎn)名字。XQuery語(yǔ)句解析算法的流程圖如圖2所示,首先取得根節(jié)點(diǎn)XQuery開始處理語(yǔ)法樹的內(nèi)容,循環(huán)三次依次得到QueryList、Module和MainModule節(jié)點(diǎn)。
判斷節(jié)點(diǎn)MainModule是否為null,如為null,則報(bào)錯(cuò);如果不為null,取出第一個(gè)節(jié)點(diǎn)prolog和第二個(gè)節(jié)點(diǎn)QueryBody,分別對(duì)這兩個(gè)節(jié)點(diǎn)進(jìn)行分析處理。
對(duì)prolog節(jié)點(diǎn)進(jìn)行處理,左節(jié)點(diǎn)prefix和右節(jié)點(diǎn)url為命名空間的格式,保存為名值對(duì)。在實(shí)際項(xiàng)目操作中,QueryBody環(huán)節(jié)只會(huì)出現(xiàn)一個(gè)FLOWR語(yǔ)句,很少會(huì)有嵌套語(yǔ)句,本文只給出FLOWR的子節(jié)點(diǎn)為ForClause的情況,其他子節(jié)點(diǎn)暫不考慮。
判斷ForClause子節(jié)點(diǎn)類型,若為用來(lái)表示變量所對(duì)應(yīng)的Xpath值PathExpr節(jié)點(diǎn),則取出PathExpr節(jié)點(diǎn)的子節(jié)點(diǎn)判斷其類型。節(jié)點(diǎn)為函數(shù)的情況下則調(diào)用預(yù)定義函數(shù),根據(jù)字段名稱在節(jié)點(diǎn)樹中定位并保存其內(nèi)容;如節(jié)點(diǎn)類型為分隔符,則表示任意節(jié)點(diǎn)都可以作為下一個(gè)節(jié)點(diǎn)字段的起始狀態(tài)。最后將PathExpr節(jié)點(diǎn)的處理結(jié)果ResultList與Varname變量節(jié)點(diǎn)對(duì)應(yīng)并保存。
2 結(jié)合SAX和DOM解析XBRL文件
對(duì)于XBRL文件來(lái)說(shuō),存在DOM和SAX兩種基本的解析手段。如果進(jìn)行一次性查詢或非頻繁性查詢,建議采用內(nèi)存消耗小的基于事件驅(qū)動(dòng)模型的SAX解析方式,無(wú)需像DOM解析方式中為所有節(jié)點(diǎn)創(chuàng)建對(duì)象。但當(dāng)需要大量上下文相關(guān)查詢及頻繁查詢時(shí),尤其在查詢后經(jīng)修改合并而得到的結(jié)果集上進(jìn)行復(fù)查詢,則采用DOM方式為好。
XBRL文件解析分為兩種情況: (1)分類標(biāo)準(zhǔn)比較穩(wěn)定,對(duì)其進(jìn)行首次框架解析后將在數(shù)據(jù)庫(kù)中將其保存,可以采取單獨(dú)的SAX解析方式簡(jiǎn)單地進(jìn)行逐條解析;(2)實(shí)例文件承載大量重要數(shù)據(jù),用戶多使用頻繁查詢及復(fù)合查詢等查詢實(shí)例文件來(lái)進(jìn)行數(shù)據(jù)分析,在這種情況下DOM解析方式是最好的選擇。但是實(shí)例文件數(shù)量較多時(shí),為XBRL實(shí)例文件中所有節(jié)點(diǎn)創(chuàng)建對(duì)象會(huì)大大增加內(nèi)存需求。這時(shí)需要考慮將這兩種方式結(jié)合起來(lái)使用。在讀取實(shí)例文件數(shù)據(jù)時(shí),利用SAX只讀取用戶所需要的若干小數(shù)據(jù)文件,并為小數(shù)據(jù)文件在內(nèi)存中建立DOM對(duì)象,每次讀取新的數(shù)據(jù)片段,則在已存在的DOM對(duì)象上進(jìn)行添加或者修改等操作。這樣做既有效地節(jié)省了大量資源,也充分利用了DOM對(duì)象的易操作性。
圖3為兩種解析方式結(jié)合的工作原理,其處理過(guò)程為:首先SAX對(duì)象objSAX的parse方法被調(diào)用來(lái)解析XBRL實(shí)例文件,在startElement事件中進(jìn)行元素篩選,如為所需元素,則保存該元素及其子節(jié)點(diǎn)元素,在endElement事件中調(diào)用DOM對(duì)象的loadXML()方法將數(shù)據(jù)轉(zhuǎn)化為DOM樹,從而可以方便下一步的數(shù)據(jù)處理(如頻繁查詢、信息更新等)。這樣不僅保證了快速解析,也在更大程度上支持XQuery的上下文查詢及信息檢索。
3 系統(tǒng)實(shí)驗(yàn)結(jié)果
實(shí)驗(yàn)環(huán)境采用Inter Pentium Dual E2160 @1.80 GHz、1 GB 內(nèi)存、Windows XP。
本文引擎解析文件時(shí)利用SAX+DOM方式,下面的實(shí)驗(yàn)結(jié)果證明了使用這種方式的優(yōu)勢(shì),如圖4所示。使用SAX+DOM方式處理時(shí),只需將所需內(nèi)容裝入內(nèi)存,故文檔處理的時(shí)間不會(huì)因?yàn)槲臋n的大小發(fā)生太大變化,事件均小于0.003 s。而采用DOM方法處理文檔,當(dāng)文檔大小達(dá)到一定程度時(shí),需要使用硬盤的虛擬內(nèi)存,其處理時(shí)間也會(huì)急劇增大。
本文所提出的查詢引擎簡(jiǎn)化了XQuery語(yǔ)句解析流程和復(fù)雜度,節(jié)點(diǎn)尋址路線相對(duì)于開源軟件XQEngine變得簡(jiǎn)單。本實(shí)驗(yàn)利用上述兩種引擎對(duì)中國(guó)Taxonomy的cas_core_2010-09-30.xsd文件進(jìn)行查詢,查詢語(yǔ)句如圖5所示,兩個(gè)解析器都正確地返回結(jié)果2 847個(gè)節(jié)點(diǎn)。本文提出的查詢引擎用時(shí)1.25 s,XQEngine因其復(fù)雜的XQuery解析算法使得用時(shí)稍長(zhǎng),為3.7 s。
本文在深入剖析XQuery查詢語(yǔ)法特點(diǎn)后,結(jié)合“SAX+自定義DOM”文件解析方式完成對(duì)FLWOR抽象語(yǔ)法樹的遍歷及查詢信息讀取,來(lái)簡(jiǎn)化XQuery語(yǔ)句的查詢處理流程并降低查詢匹配的復(fù)雜度,設(shè)計(jì)并實(shí)現(xiàn)了XBR查詢引擎,提高了查詢效率,降低了內(nèi)存消耗。該引擎在項(xiàng)目中的數(shù)據(jù)信息查詢模塊起著重要作用。
參考文獻(xiàn)
[1] 呂科,劉曉峰.XBRL技術(shù)原理與應(yīng)用[M].北京:電子工業(yè)出版社,2007.
[2] WALMSLEY P. XQuery權(quán)威指南[M].王銀輝,譯.北京:電子工業(yè)出版社, 2009.
[3] 馮進(jìn),丁博,史殿習(xí),等.XML解析技術(shù)研究[J].計(jì)算機(jī)工程與科學(xué),2009,31(2):120-124.
[4] 楊波.DOM解析器OnceDOMParser的設(shè)計(jì)與實(shí)現(xiàn)[D].北京:中國(guó)科學(xué)院研究生院(軟件研究所),2005.
[5] 孟曉峰,王宇,王小峰. XML查詢優(yōu)化研究[J]. 軟件學(xué)報(bào), 2006,17(10):2069-20.
[6] PAPARIZOS S, PATEL J M, JAGADISH H V. SIGOPT:Using schema to optimize XML query processing international[C]. Istanbul: International Conference on Data Engineering, 2007.
[7] 華珊珊,謝鉉洋.XML查詢語(yǔ)言XQuery的研究與實(shí)現(xiàn)[J].計(jì)算機(jī)技術(shù)與發(fā)展, 2009,19(4): 48-50.
[8] VISWANDAHA S, SANKAR S. Java Compiler Compiler(JavaCC)-The java papser generator[J].URL:https://javaCC.dev.java.net.2006.