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