• 沒有找到結果。

一般路徑檢索(General Path Query)

第四章 路徑表示式檢索實作說明

第二節 一般路徑檢索(General Path Query)

這 類 的 檢 索 支 援 了 萬 用 字 元(Wild Cards)與 常 規 表 示 式 (Regular Expressions),因此在路徑條件的檢索上比Simple Path Query來的強大。對於萬 用字元,我們實作了「%」與「#」的功能,其中「%」的意義如同Simple Path Query 的近似搜尋,但情況發生於元素節點上,如圖 13 中的節點 PLAYER 下有兩個 子節點為 SURNAME 與 G_NAME,當路徑條件下某個節點為%NAME 時,則 SURNAME 與 G_NAME 皆會被挑出以進行路徑比對。而另一個符號「#」則表 示從某個節點開始,中間可經過0個以上的節點以到達另一個節點,「#」符號常 用 在 使 用 者 不 知 道 文 件 結 構 的 情 況 下 。 如 路 徑 條 件

「SEASON.#.PLAYER.G_NAME」則表示從節點「SEASON」開始,不管中間經 過幾個節點,只要最後節點路徑為「PLAYER.G_NAME」即滿足條件。

至於常規表示式,我們實作了Optional Node —「(.node)?」的功能,表示路 徑 中 可 出 現 0 次 或 1 次 的 「node」 節 點 。 舉 例 來 說 , 若 路 徑 條 件 為

「PLAYER(.NAME)?.G_NAME」, 則 進 行 路 徑 檢 索 時 , 須 比 對 兩 個 路 徑

「PLAYER.NAME.G_NAME」或「PLAYER.G_NAME」是否滿足條件。下列即 對「#」、「%」與「(.node)?」三種功能之演算法做說明。

IF (pathNodeElement = ){

// 取出 queryPath 中 wildcard 前的 Element 節點資訊

nodeElementBfWildCard = GetElementBfWildCard(queryPath);

// 透過 DID 與 UID 來找出其父節點資訊,直到父節點與WildCard 前 的節點資訊相同時再做最後的 PathCheck

While (nodeValue != nodeElementBfWildCard){

IF (nodeValue = elmSelectPattern){ //判斷是否為欲挑選的節點 //若 matchedEleSeqId 中沒出現過 node SeqId

//則將 nodeSeqId 加入 matchedEleSeqId

IF (!CheckContain(matchedEleSeqId, nodeSeqId)) matchedEleSeqId.addElement(nodeSeqId);

}

pUID = (UID-2)/MaxBranch + 1;

ResultSet node = SelectNode(DID, pUID);

nodeSeqId = node.getBigDecimal("seqId");

nodeValue = node.getString("value");

}

subPath = GetSubQueryPathBfWildCard(queryPath);

PathCheck(DID, pUID, subPath, elmtPattern);

}

"#"

圖 18:WildCardOperation("#") 路徑檢查演算法

若路徑條件為「SEASON.LEAGUE.#.G_NAME」,當進行路徑比對中發現目 前的節點為「#」時,此時將萬用字元前的節點以 nodeElementBfWildCard 記錄 之,接著遞迴進行上層父節點比對直到該節點為萬用字元前的節點後,再做最後 的路徑比對以檢查是否滿足路徑條件。往上層父節點尋找的過程中,若有出現欲 挑選的節點時,則須將節點的SeqId記錄之。以前述之路徑條件而言,以下即為 處理符號「#」的步驟:

1. 開始進行路徑比對時,由滿足檢索條件值的 UID 得知其父節點為 G_NAME,路徑條件中最外部的節點確實為 G_NAME。滿足路徑條件 後繼續進行上一層路徑「SEASON.LEAGUE.#」比對。

2. 出現符號「#」,此時nodeElementBfWildCard設為LEAGUE。接著由節 點G_NAME之UID往上層父節點推導,直到節點為LEAGUE止。

3. 接著,再由節點LEAGUE進行更上層路徑「SEASON.LEAGUE」比對。

「%」:演算法如圖 19 所示。

IF (percentOccur){

IF (percentAtHead) {

//WildCard %出現在 Element 首與尾,如%NAME%

pathNodeElement = RemovePercentAtHead(pathNodeElement);

IF (pathNodeElement End With percent) {

pathNodeElement = RemovePercentAtTail(pathNodeElement);

IF (nodeValue Contains Substring pathNodeElement){

//目前節點資料滿足路徑條件則繼續遞迴比較上一層父節點是否 亦滿足

pUID = (UID-2)/MaxBranch + 1;

subPath = GetSubQueryPath(queryPath);

PathCheck(DID, pUID, subPath, elmtPattern);

}

} ELSE IF (nodeValue Ends With Substring pathNodeElement){

//WildCard %出現在 Element 首,如%NAME

//目前節點資料滿足路徑條件則繼續遞迴比較上一層父節點是 否亦滿足

pUID = (UID-2)/MaxBranch + 1;

subPath = GetSubQueryPath(queryPath);

PathCheck(DID, pUID, subPath, elmtPattern);

} } ELSE {

//WildCard %出現在 Element 尾,如 NAME%

pathNodeElement = SubStringRemoveWildCard(pathNodeElement);

IF (nodeValue Begins With pathNodeElement) {

//目前節點資料滿足路徑條件則繼續遞迴比較上一層父節點是否 亦滿足

pUID = (UID-2)/MaxBranch + 1;

subPath = GetSubQueryPath(queryPath);

PathCheck(DID, pUID, subPath, elmtPattern);

} } }

19 WildCardOperation("%")

路徑比對的過程中,若路徑條件中的節點出現符號「%」時,只有當該節點 滿足近似搜尋所述的三種情況下,才會繼續進行上一層的路徑條件比對。舉例而 言,路徑條件若為「DIVISION.PLAYER.%NAME」,則開始進行路徑比對時,由 滿足檢索條件值的UID得知其父節點為G_NAME,該節點確實由NAME結尾。

因此滿足路徑條件接著繼續進行上一層路徑「DIVISION.PLAYER」比對。

「(.node)?」:演算法如圖 20 所示。

IF (questionMarkOccur){ //出現 Optional 的情況 如 a(.b)?.c //分兩種情形繼續遞迴搜尋

subPath = GetPathContainOptionalNode(queryPath);

PathCheck(DID, pUID ,subPath, elmtPattern); //Optional 的節點有出現 subPath = GetPathNotContainOptionNode(queryPath);

PathCheck(DID, pUID, subPath, elmtPattern); //Optional 的節點沒有出現 }

圖 20:OptionalNodeOperation( ) 路徑檢查演算法

當Optional Node的條件出現時,路徑條件將分成包含Optional Node與不包 含Optional Node的情況繼續進行上一層的路徑比對。舉例而言,假設路徑條件 為「DIVISION.PLAYER(.NAME)?.G_NAME」,當比對到節點 G_NAME 時,發 現路徑條件中出現Optional Node –「NAME」。此時,路徑條件可為兩種情形,

一條路徑為包含Optional Node,即「DIVISION.PLAYER.NAME.G_NAME」

,另一條則否,即「DIVISION.PLAYER.G_NAME」。接著再以這兩種路徑條件 個別進行路徑比對。

相關文件