1.引言?
??? 近年來(lái),,地理信息系統(tǒng)(GIS)發(fā)展迅速,。為了在全球范圍內(nèi)實(shí)現(xiàn)GIS軟件組件的互操作性,,OGC(Open GIS Consortium)提出了空間要素服務(wù)(WFS)的實(shí)現(xiàn)規(guī)范[1],有利于解決基于Web的GIS軟件的數(shù)據(jù)共享,、互操作性和開(kāi)放性等問(wèn)題,。
??? WFS是OGC提出的一種空間要素服務(wù)。它將Web服務(wù)應(yīng)用于地理信息系統(tǒng),,允許客戶端通過(guò)互聯(lián)網(wǎng)從多個(gè)服務(wù)器端獲取以地理標(biāo)注語(yǔ)言GML(Geography Markup Language)編碼的空間地理數(shù)據(jù),。
??? 空間數(shù)據(jù)的查詢是通過(guò)發(fā)送GetFeature請(qǐng)求來(lái)實(shí)現(xiàn)的。在WFS的實(shí)現(xiàn)規(guī)范中,,一個(gè)GetFeature請(qǐng)求是由空間要素類型,、屬性和查詢條件三部分組成,以XML格式定義,。其中要素類型用于指定查詢哪類要素,,屬性用于指定需獲取該要素的哪些屬性,而查詢條件用于篩選出滿足指定條件的要素,。?
??? 我們的課題是需要實(shí)現(xiàn)一個(gè)基于J2EE的WFS系統(tǒng),;其中存儲(chǔ)空間數(shù)據(jù)的數(shù)據(jù)源采用的是ArcSDE(ESRI公司開(kāi)發(fā)的空間數(shù)據(jù)庫(kù)軟件),在查詢數(shù)據(jù)源ArcSDE時(shí)使用其自身提供的客戶端應(yīng)用接口,。由于ArcSDE應(yīng)用接口與WFS應(yīng)用接口之間存在著差異,,因此需要對(duì)收到的WFS GetFeature請(qǐng)求作一些適當(dāng)?shù)淖儞Q,以適應(yīng)ArcSDE的數(shù)據(jù)查詢,。
??? 本文將著重介紹以WFS GetFeature請(qǐng)求查詢ArcSDE的實(shí)現(xiàn)方法,,以及必要的變換算法。
2.設(shè)計(jì)思想?
??? WFS應(yīng)用接口與ArcSDE應(yīng)用接口之間的主要差異在于查詢條件的設(shè)置。
首先,,在數(shù)據(jù)格式方面,,WFS GetFeature請(qǐng)求中的查詢條件是以XML格式定義,而ArcSDE的應(yīng)用接口不支持XML,,因此需要對(duì)此XML字符串進(jìn)行解析,。
??? 其次,,在數(shù)據(jù)內(nèi)容方面,,GetFeature的查詢條件可以分為兩類,一類以要素標(biāo)識(shí)符作為查詢條件,;另一類是由空間篩選條件,,或者非空間篩選條件,或者這二者的邏輯組合組成的查詢條件,。每次查詢只能選用其中一類查詢條件,,兩類不能同時(shí)出現(xiàn)在一次查詢中。對(duì)第一類GetFeature的查詢條件,,在ArcSDE的應(yīng)用接口中提供了一種用要素標(biāo)識(shí)符作為約束條件的篩選器對(duì)象來(lái)處理此類條件,。對(duì)于第二類查詢條件,在ArcSDE中可以通過(guò)定義SQL屬性查詢來(lái)處理GetFeature請(qǐng)求中的非空間篩選條件,,而通過(guò)添加空間約束的篩選器則可處理請(qǐng)求中的空間篩選條件,。對(duì)于空間和非空間篩選條件的邏輯組合組成的條件,則相對(duì)不易處理,。由于在查詢ArcSDE時(shí)空間篩選器需以數(shù)組的形式設(shè)置,,使得空間篩選條件之間只能以邏輯“與”的關(guān)系進(jìn)行組合。同樣,,由于空間和非空間篩選分開(kāi)設(shè)置,,使得空間與非空間篩選條件之間也只能以邏輯“與”的關(guān)系進(jìn)行組合。而在實(shí)際的GetFeature請(qǐng)求的查詢條件中,,查詢請(qǐng)求可能是由“與”,、“或”、“非”三種邏輯關(guān)系任意混合組成,,條件之間的組合不一定能滿足上述ArcSDE篩選條件的要求,。我們?cè)谶@里提出了一種解決的方案:對(duì)查詢條件提取析取范式,轉(zhuǎn)換成多個(gè)“與”項(xiàng)組合(有的與項(xiàng)組合有可能只有一項(xiàng))的并集,,然后對(duì)每個(gè)“與”項(xiàng)組合組織一次子查詢,,每次得到一個(gè)結(jié)果集,最后對(duì)所有的結(jié)果集再取并集,,即為整個(gè)查詢的結(jié)果集,。
3.算法設(shè)計(jì)?
??? 根據(jù)上面分析的結(jié)果,將整個(gè)查詢變換分為兩個(gè)步驟:
??? (1)對(duì)XML格式的查詢條件進(jìn)行DOM解析。DOM處理XML文檔時(shí)會(huì)將XML文檔加載到內(nèi)存中生成一棵DOM節(jié)點(diǎn)樹,,可以方便地實(shí)現(xiàn)遍歷,。
??? (2)對(duì)查詢條件提取析取范式,將不符合ArcSDE要求的查詢條件拆分為多次,。
??? (2.1)遍歷DOM樹同時(shí)生成BLRTree,,用以去除Not節(jié)點(diǎn),并將非空間條件轉(zhuǎn)換為SQL語(yǔ)句,,將空間條件封裝為特定的類結(jié)構(gòu),。
??? 由于在GetFeature查詢條件的DOM樹中的可能存在著Not節(jié)點(diǎn),而且根據(jù)GetFeature查詢條件的格式,,所有單個(gè)的空間或非空間篩選條件在樹中是以一棵子樹的形式存在,,而不是一個(gè)節(jié)點(diǎn),因此還不能直接作邏輯關(guān)系的轉(zhuǎn)換,,需要對(duì)這棵DOM樹進(jìn)行“化簡(jiǎn)”,。為了不改變?cè)瓨涞倪壿嫞疚亩x了一種二叉樹數(shù)據(jù)結(jié)構(gòu)BLRTree(二元邏輯關(guān)系樹—Binary Logic Relation Tree),。在遍歷原DOM樹的過(guò)程中,,自底向上構(gòu)造這一數(shù)據(jù)結(jié)構(gòu)。在BLRTree中,,所有的樹枝節(jié)點(diǎn)都是二元邏輯運(yùn)算符“And”或“Or”,,而所有的葉子節(jié)點(diǎn)都是單個(gè)的查詢條件。這種處理是將Not節(jié)點(diǎn)作為函數(shù)遞歸的一個(gè)布爾值參數(shù)truth傳遞給下層,,在沒(méi)有遇到Not節(jié)點(diǎn)時(shí),,truth都為“true”,而如果遇到了Not節(jié)點(diǎn),,只是將truth取反(注意:是取反,,而不是取“false”值),并不在Not節(jié)點(diǎn)上作任何處理操作,,這樣對(duì)其下層的子節(jié)點(diǎn)就可以根據(jù)truth的取值來(lái)進(jìn)行構(gòu)造相應(yīng)的了BLRTree子樹,。原DOM樹中的所有Not節(jié)點(diǎn)在BLRTree中已根據(jù)摩根定率降至葉子節(jié)點(diǎn)處,且不以節(jié)點(diǎn)的形式存在,,而并作為條件節(jié)點(diǎn)的一個(gè)布爾值參數(shù),。
??? (2.2)遍歷(后序)BLRTree同時(shí)生成O_A_C_Tree,根據(jù)分配率和結(jié)合律進(jìn)行邏輯關(guān)系變換提取析取范式,。
??? BLRTree樹構(gòu)造完畢后,,如果發(fā)現(xiàn)樹根是一個(gè)條件節(jié)點(diǎn),則不必作邏輯關(guān)系轉(zhuǎn)換,。如果是邏輯操作符節(jié)點(diǎn)則需進(jìn)行邏輯關(guān)系的轉(zhuǎn)換,。由于最終的結(jié)果是多個(gè)與項(xiàng)組合的并集(析取范式結(jié)構(gòu)),,即將多個(gè)與項(xiàng)組合“或”起來(lái)。若把每個(gè)與項(xiàng)組合中的所有條件項(xiàng)看作是同一層,,而把每個(gè)與項(xiàng)組合之間看作是同一層,,最上層的“或”關(guān)系為一層,則可將一個(gè)多個(gè)與項(xiàng)組合的并集用一種3層孩子兄弟樹的結(jié)構(gòu)來(lái)表示,。因此定義了一種3層孩子兄弟樹的數(shù)據(jù)結(jié)構(gòu)O_A_C_Tree(Or-And-Condition Tree)來(lái)輔助轉(zhuǎn)換,。在后序遍歷BLRTree的同時(shí),從條件節(jié)點(diǎn)開(kāi)始構(gòu)造子樹,。如遇到Or節(jié)點(diǎn),,則通過(guò)結(jié)合律將左右子樹進(jìn)行合。而遇到And節(jié)點(diǎn),,則通過(guò)分配律將左右子樹進(jìn)行合,。如此遞歸操作生成一棵完整的O_A_C_Tree,,完成邏輯關(guān)系的轉(zhuǎn)換,。
??? (2.3)遍歷O_A_C_Tree,將所有篩選條件放置到兩個(gè)數(shù)組中,,以便于訪問(wèn),。
??? 完成了邏輯轉(zhuǎn)換之后,原查詢條件將被放置到兩個(gè)數(shù)組whereclauses[]和spatialfilters[][]中,。其中whereclauses[]是非空間條件組,,數(shù)組中每個(gè)元素代表一次查詢的非空間篩選條件。由于非空間篩選條件是以SQL語(yǔ)句的形式存在,,一次子查詢中的非空間篩選條件用邏輯“與”可合并為一個(gè)整體,,因此一次子查詢中的所有非空間篩選條件可以合并只用一個(gè)元素來(lái)表示。spatialfilters[][]是空間條件數(shù)組,,數(shù)組中的每一維代表一次子查詢的所有空間篩選條件,。用whereclauses[]中的一個(gè)元素,再搭配spatialfilters[][]中的相應(yīng)一組元素(如whereclauses[i]和spatialfilters[i][]可以構(gòu)成第i次子查詢的篩選條件)就可以構(gòu)成一次ArcSDE子查詢的全部篩選條件,。
??? 如此便可完成一次查詢變換,,根據(jù)數(shù)組的內(nèi)容就可以設(shè)置相應(yīng)的篩選條件,進(jìn)行查詢,。在處理結(jié)果時(shí),,將每個(gè)取到的結(jié)果其封裝成GML格式,寫到輸出流中,。這樣不必保存查詢的要素對(duì)象實(shí)體,,降低了系統(tǒng)開(kāi)銷。由于在對(duì)組合條件進(jìn)行條件拆分的時(shí)候,,將一次查詢分成了多次子查詢,,因此每次子查詢的結(jié)果集之間可能會(huì)有重復(fù)的情況,,這時(shí)需要將其中重復(fù)的結(jié)果舍去。由于要素標(biāo)識(shí)符都是唯一確定的,,這樣只需把查到過(guò)的要素標(biāo)識(shí)符記錄下來(lái),,下次再遇到標(biāo)識(shí)符相同的要素將會(huì)跳過(guò)而不做任何操作。由于查詢的數(shù)據(jù)量可能會(huì)很大,,如果只將標(biāo)識(shí)符的值順序的存儲(chǔ)在一個(gè)表中,,進(jìn)行查找的開(kāi)銷會(huì)很大,因此為了利于新值的插入和加快查找的速度,,本文選擇以二叉排序樹為存儲(chǔ)結(jié)構(gòu),,使用了二叉樹查找算法。
4.算法實(shí)現(xiàn)?
?? 關(guān)鍵算法:
算法2.1 構(gòu)造二元邏輯關(guān)系樹:?
BLRTreeNode construct ( Node root , boolean truth ){? //root 為DOM樹中的根節(jié)點(diǎn)?
?????? if? root為and(/or)? Then? ?
對(duì)root的左子樹作construct( root.Lchild , truth )得到Lchild ?
對(duì)root的右子樹作construct( root.Rchild , truth )得到Rchild ?
if? truth為true Then?
創(chuàng)建一個(gè)and(/or)節(jié)點(diǎn),,將Lchild,,Rchild作為左右孩子?
Else?
創(chuàng)建一個(gè)or(/and)節(jié)點(diǎn),將Lchild,,Rchild作為左右孩子?
Endif?
返回新創(chuàng)建的節(jié)點(diǎn)?
Endif?
if? root為not?? Then? //not是單目的邏輯運(yùn)算符,,只有一棵子樹?
????????????? if? root的孩子也為not? Then?
????????????? ???? 對(duì)root的孫子樹作construct(root.Grandchild, truth)?
????????????? ???? 得到grandchild節(jié)點(diǎn),將其返回?
????????????? Else?
truth取反?
對(duì)root的子樹作construct(root.child, truth)?
得到child節(jié)點(diǎn),,將其返回?
????????????? Endif?
?????? Endif?
?????? if? root為非空間條件節(jié)點(diǎn)??? Then?
????????????? ?? 根據(jù)truth 構(gòu)造非空間條件節(jié)點(diǎn), 將其返回?
Else if? root為空間條件節(jié)點(diǎn)??? Then?
????????????? ?? 根據(jù)truth 構(gòu)造空間條件節(jié)點(diǎn), 將其返回?
?????? Endif?
}?
算法2.2? 等價(jià)構(gòu)造析取范式結(jié)構(gòu)樹:?
ORNode LogicTransform ( BLRTreeNode root ){? //root 是BLRTree的根節(jié)點(diǎn)?
if? root . Lchild是條件節(jié)點(diǎn)??? then?????? ?
????????????? 生成condNode節(jié)點(diǎn)cond1 ?
??? ? ??? 新添一個(gè)ANDNode節(jié)點(diǎn)and1,,孩子指針指向cond1?
?????? 新添一個(gè)ORNode節(jié)點(diǎn)or1,孩子指針指向and1?
Else? 對(duì)左子樹作LogicTransform (root . Lchild ),,得到or1?
Endif?
if? root . Rchild是條件節(jié)點(diǎn)??? then?????? ?
????????????? 生成condNode 節(jié)點(diǎn)cond2?
?????? 新添一個(gè)ANDNode節(jié)點(diǎn) and2,,孩子指針指向cond2?
??? ? ??? 新添一個(gè)ORNode 節(jié)點(diǎn)or2,孩子指針指向and2?
Else? 對(duì)右子樹作LogicTransform (root . Rchild ),,得到or2?
Endif?
? if?? root為Or節(jié)點(diǎn)? then? ?? ?
將or2節(jié)點(diǎn)的所有孩子添加到or1節(jié)點(diǎn)的孩子鏈上去?
?????? 返回or1節(jié)點(diǎn)?
Endif?
? if?? root為And節(jié)點(diǎn)? then?
新添一個(gè)ORNode節(jié)點(diǎn)newOR?
for( i = 0,;i < or1節(jié)點(diǎn)孩子個(gè)數(shù);i++ ) {?
? for( j = 0,;j < or2的孩子個(gè)數(shù),;j++) {?
新添一個(gè)ANDNode節(jié)點(diǎn)newAnd?
將or1的第i個(gè)孩子的所有子孩子和or2的第j個(gè)孩子的所有子孩子都添加到newAnd節(jié)點(diǎn)的孩子鏈上去,作為newAnd的共同的孩子?
為newOR的添加一個(gè)孩子newAnd?
?????? }?
}?
?????? 返回newOR節(jié)點(diǎn)?
Endif?
}n ??? 下面舉一實(shí)例來(lái)表現(xiàn)轉(zhuǎn)換的全過(guò)程:? ??? 要求查找所有屬于M州,,且不同時(shí)滿足人口大于100000和與一條起止點(diǎn)坐標(biāo)為(-50 20,,-57 22)的河流相交的城市。? 查詢條件如下:? ??? ? ??????? ??????????? ??????????? ??????? ? ??????? ??????????? ??????????? ??????????????? < gml:coordinates>-50,20 –57,22 gml:coordinates>? ??????????? ? ??????? ? ??? ? ? (1)對(duì)XML的查詢條件進(jìn)行DOM解析后,,生成DOM節(jié)點(diǎn)樹? ?????? (2.1)遍歷DOM樹同時(shí)生成BLRTree: 圖1? 生成BLRTree? ?????? (2.2)遍歷BLRTree樹同時(shí)生成O_A_C_Tree? 圖2? 生成O_A_C_Tree? ?????? (2.3)遍歷O_A_C_Tree輸出到數(shù)組中? whereclauses[0] =? “StateName=‘M’ And Not Population >100000”? ???? whereclauses[1] =? “StateName=‘M’”? n? n? filters[0]置空 filters[1][0]為不滿足與線相交的空間條件 5,、結(jié)束語(yǔ) ??? 本文在對(duì)比了WFS GetFeature查詢請(qǐng)求的格式與數(shù)據(jù)源ArcSDE的查詢的基礎(chǔ)上,提出了一種將WFS的要素查詢變換為ArcSDE查詢對(duì)象的變換算法,,并著重介紹了以WFS的應(yīng)用接口對(duì)數(shù)據(jù)源ArcSDE進(jìn)行查詢實(shí)現(xiàn)的實(shí)現(xiàn)方法,。 ??? 在轉(zhuǎn)換的過(guò)程中為了實(shí)現(xiàn)數(shù)據(jù)的接口一致性,進(jìn)行一系列的數(shù)據(jù)轉(zhuǎn)換,,這勢(shì)必增加系統(tǒng)的負(fù)擔(dān),,降低系統(tǒng)的效率,。因此,還需要在系統(tǒng)的優(yōu)化方面作進(jìn)一步的研究,。 參考文獻(xiàn) 1.?Open GIS Consortium Inc.,,F(xiàn)eature Service Implementation Specification 1.0.0 (02-058) ,Version 1.0.0, 19-September-2002 2.?Open GIS Consortium Inc.,,OpenGIS Filter Encoding Implementation Specification 1.0.0 (02-059),,Version 1.0.0, 19-September-2001 3.?Open GIS Consortium Inc.,OpenGIS Geography Markup Language (GML) Implementation Specification (02-009),,Version 2.1.1, 25-April-2002 4. ESRI,,ArcSDE Developer Help 8.3 2003年 5.?Don Box, Aaron Skonnard和John Lam著,卓棟濤譯,。XML 本質(zhì)論,。中國(guó)電力出版社,2003年3月第一版