XML 程式設計思想:將檔案合併到 RDF 模型和基本的 RDF 查詢(轉)

amyz發表於2007-08-12
XML 程式設計思想:將檔案合併到 RDF 模型和基本的 RDF 查詢(轉)[@more@]

  這篇“Thinking XML”專欄文章演示瞭如何將從多個 XML 源文件中收集的後設資料合併到用於有效查詢的單個“資源描述框架”(Resource Description Frame (RDF))模型中。專欄作家 Uche Ogbuji 在前一篇中介紹瞭如何一起使用 XML 和 RDF 來進行知識管理,本文是上一篇的繼續,在本文中他論述了基於用從現有的 XML 格式獲取的資料組成 RDF 模型的技術。該文的中心是一個示例,在該示例中,擴充套件基於 Web 的問題跟蹤器(最初開發它來操縱 XML 格式的應用程式資料)來利用 RDF。XSLT 和 Python 樣本程式碼清單演示了將來自 XML 檔案的後設資料聚合到單個 RDF 模型(一個使用 XSLT ,另一個使用 RDF)以及簡單 RDF 查詢的示例。

  在本專欄的前一篇文章中,即 知識管理的基本 XML 和 RDF 技術,第一部分(在繼續閱讀之前,可能需要重新回顧一下),介紹了一個基於收集的資料(以 XML 格式表示)的問題跟蹤器應用程式示例。然後演示瞭如何使用 XSLT 從應用程式資料中抽取 RDF。

  本專欄文章透過演示如何組合由轉換每個 XML 源文件所建立的離散的 RDF 片段來完成這些事情。同時還演示了一些基本的查詢技術。

  資源批次派生

  在上篇專欄文章中,完成了一個從 XML 原始檔中抽取作為序列化格式的 RDF 的練習。然而,知識管理的大多數有用之處在於操縱 RDF 語句的抽象模型,而不是個別序列化檔案。RDF 模型是圖形結構,該結構可以非常簡單也可以令人難以置信的複雜。(事實上,極端情況下,Semantic Web 的設想是要建立至少同當前 Web 一樣大的 RDF 模型。如果實現該模型的話,它可能是曾經在使用中的最大的計算機資料結構。)

  迄今為止,問題跟蹤器的示例是由一組 XML 檔案組成的,這些檔案是 RDF 模型各部分的序列化。每一部分就象七巧板中的一塊,如果將它們組合到一塊兒,將表示問題跟蹤器應用程式中所有資料的 RDF 模型。每一部分本身並不十分重要,因此下一步來討論如何建立一幅完整的“圖畫”,該“圖畫”才是知識管理的真正價值所在。

  使用 XSLT 進行批次轉換

  拼裝該“圖畫”的一種選擇是根本不處理七巧板塊,而是使用 XSLT 一勞永逸地生成該“圖畫”。可以編寫一個轉換,該轉換收集每個 XML 問題文件,並運用前一篇文章中所描述的 RDF 轉換處理,然後將每次轉換結果累積到一個序列化 RDF 結果。要做到這一點,需要利用標準的 document() XSLT 函式,該函式可以讀入任意的文件,這些文件是作為用於轉換的補充性 XML 源文件。

  document() 函式需要知道所要讀入文件的準確名稱。XSLT 沒有(比如說)透過使用萬用字元來讀入多個文件的標準機制。可以透過許多方法解決這一問題(包括藉助於 XSLT 擴充套件,該擴充套件允許透過萬用字元或其它機制來批次裝入文件)。然而,因為這不是本示例的中心問題,所以選擇建立帶有每個問題文件清單的集中(hub) XSLT 文件這項折中方案。清單 1 issue-hub.xml 用指定的兩個問題文件(在前一篇專欄文章中介紹過)來演示集中文件是什麼樣子的。

  清單 1:帶有每個應用程式資料文件的問題文件清單的集中 XML 文件。

   issue1.xml issue2.xml

  一旦有了集中文件,就可以將 清單 2metadata-batch.xslt 中的轉換應用到作為源文件的集中文件中以從所有列出的問題中建立聚合 RDF。

  清單 2 看起來可能非常熟悉;其中大多數同前一篇文章中的轉換相同。這是因為我很留意 XML 結構的模組化處理。根模板現在從集中文件中查詢每個 issue 元素(注意,這裡使用空名稱空間)。然後它從每個元素內容中指定的檔名裝入文件。注意,這裡使用 document(.)/* 而不僅僅是 document(.) 。這種構造防止處理器匹配問題文件的根節點,這會結束呼叫打算用於集中文件根節點的模板。那些正是本專欄文章的批次轉換中的唯一區別。

  可以使用任何 XSLT 處理器來執行該轉換。我使用 4XSLT 來執行轉換,如下所示:

$ 4xslt -o issues.rdf issue-hub.xml metadata-batch.xslt

  該轉換導致 issues.rdf 中的序列化 RDF,它包含來自 issue1.xml 和 issue2.xml 中的後設資料。

  使用 RDF 工具進行批次轉換

  將多個 XML 文件聚合到單個 RDF 模型中的另一種選擇是(如前一篇文章所述)分別構建每個 RDF 文件,然後使用 RDF 解析器將所有的文件解析成單個抽象模型。例如,透過對從前面一篇專欄文章中的示例問題檔案中生成的兩個 RDF 檔案使用 4RDF,將得到清單 3。

  清單 3:從 XML 檔案中派生,並由 RDF 解析器(這裡是 4RDF)分析的兩個 RDF 問題檔案的批次轉換結果

  $ 4rdf -d 1.rdf 2.rdfThe following is a list of resulting tuples, each in the form "subject,predicate, object".[("","","#i2001030423"),("#anonymous:e08-e06-30b-90d-a060005104", "id", "i2001030423"),("#anonymous:e08-e06-30b-90d-a060005104","",""),("#anonymous:1040d07-20b-909-407-b0e0402205","", "AlexandreFayolle "),("#anonymous:1040d07-20b-909-407-b0e0402205","", "Theabbreviation in listing 8 doesn't seem necessary to Nico Chauvat orme."),("#anonymous:e08-e06-30b-90d-a060005104","","#anonymous:1040d07-20b-909-407-b0e0402205"),("#anonymous:60e0b06-50a-80c-90c-50a0a08602","",""),("#anonymous:60e0b06-50a-80c-90c-50a0a08602","",""),("#anonymous:e08-e06-30b-90d-a060005104","","#anonymous:60e0b06-50a-80c-90c-50a0a08602"),("","","#i2001042003"),("#anonymous:2030002-506-10a-201-f090809c08", "id", "i2001042003"),("#anonymous:2030002-506-10a-201-f090809c08","",""),("#anonymous:c000706-b0b-d02-d0a-e050c0460b","", "AlexandreFayolle "),("#anonymous:c000706-b0b-d02-d0a-e050c0460b","", "I agree"),("#anonymous:2030002-506-10a-201-f090809c08","","#anonymous:c000706-b0b-d02-d0a-e050c0460b"),("#anonymous:b0c0c00-800-2-c08-20a0d0f209","",""),("#anonymous:b0c0c00-800-2-c08-20a0d0f209","",""),("#anonymous:2030002-506-10a-201-f090809c08","","#anonymous:b0c0c00-800-2-c08-20a0d0f209"),]

  清單 3 中第一行裡的 -d 選項告訴 $RDF 將 subject/predicate/object 三元組從抽象 RDF 模型轉儲到命令列,該命令列顯示清單 3 的剩餘部分.

  一旦有了問題跟蹤器的完整 RDF 模型,可能希望以一種更易於閱讀的格式而不是清單 3 中所顯示的那種格式來檢視它。例如,如果以清單 3 中的聚合 RDF 檔案為例,並使用 Dan Brickley 的 RDF 視覺化工具(請參閱 參考資料)來處理它,將得到一幅類似 圖 1的圖表。對於一般的膝上電腦螢幕來說,它可能太寬,因此請單擊連結在單獨的視窗中開啟圖表。

  圖 1 中的視覺化顯示的好處在於:可以立即辨別出某種模式,譬如使用者“uogbuji”的投稿和職責。當然,我必須承認 RDF 中隨同 URI 而來的冗長的識別符號妨礙了這一清晰性。

  跨系統查詢

  擁有可用後設資料的 RDF 模型的另外一個立杆見影的好處在於:它使許多系統級查詢(相對於編寫針對一組 XML 文件的 XPath 查詢,或將資料集中到專用資料結構以用於查詢)變得更簡單更一般。雖然,“XML 查詢語言”(XQuery)和 XML 資源庫供應商提供的專用文件收集查詢工具的出現也幫助解決了這一需求,但是現在可以使用 RDF,至少這種基本模型是標準化的。

  遺憾的是,RDF 模型的查詢還不是標準化的,這是 RDF 社群需要填補的非常重要的漏洞。幸運的是,由於 RDF 模型的簡單性,所以非常容易透過基本模式匹配來構建幾乎所有形式的查詢。這是 4RDF 中所使用的基本方法,其中,查詢就是就是查詢語句三元組的過程,該三元組匹配給定的主語、謂語和賓語模式。作為示例,請看錶 1 中剛建立的部分統一模型。

  表 1 .來自問題跟蹤器資料的一些語句

  主語: #anonymous:a0d010d-f0c-706-20e-80a0407606謂語: 賓語: Organize a vote on this topic主語: #anonymous:a0d010d-f0c-706-20e-80a0407606謂語: 賓語: 主語: #anonymous:402000d-403-309-c01-9080a205謂語: 賓語: Correct all to use the "0/1" form in the next draft.主語: #anonymous:402000d-403-309-c01-9080a205謂語: 賓語:

  有了這些三元組,就會非常容易地明白別人是如何會簡單地詢問如下問題:“給使用者 uogbuji 分配的操作標識是什麼?”以及“每個操作的主體是什麼?”。將第一個問題轉換成查詢匹配下列模式的三元組,這裡的“*”是匹配任何值的萬用字元:

  主語 謂語 賓語 *

  對此的響應之一是帶有主語“#anonymous:a0d010d-f0c-706-20e-80a0407606”(表示匹配的操作標識)的語句。注意,該標識是由 4RDF 為匿名資源(如果資源沒有標識,則由應用程式顯式地分配一個)生成的特殊標識。構成全球唯一識別符號(UUID)的一個十六進位制值緊跟在“anonymous”序列之後。有了這個標識,第二個示例問題相當於匹配下列模式,該模式返回帶有賓語“Organize a vote on this topic”的語句:

  主語 謂語 賓語 #anonymous:a0d010d-f0c-706-20e-80a0407606*

  建立在這一簡單的想法上,幾乎任何形式的 RDF 查詢(甚至關係型(SQL)查詢和物件(OQL)查詢的等價查詢)都是可能的。

  編碼 RDF 查詢

  清單 4 中的 Python 程式 query1.py 透過模式匹配、讀入 issues.rdf 檔案以及列印 uogbuji 的所有任務的主體,使用 4RDF 來運用這項查詢技術。(如果沒有使用 Python,當然可以使用其它 RDF 查詢工具,譬如 RDFDb、Jena 或列在 參考資料中“Dave Beckett 的 RDF 資源指南”中的工具。)

  清單 4:演示一個 RDF 模型簡單查詢的 Python 程式。

   from Ft.Rdf import Util#Returns an RDF model object, and the database instance it uses for#persistence (in our case, it's just a memory data structure)model, db = Util.DeserializeFromUri('issues.rdf')db.begin()USER_ID_BASE = ''IT_SCHEMA_BASE = ''print 'Actions assigned to uogbuji:'#None is used as the wild-cardmatching_statements = model.complete(None,                   IT_SCHEMA_BASE+'assign-to',                   USER_ID_BASE+'uogbuji'                   )for statement in matching_statements:  id = statement.subject  matching_statements = model.complete(id,                     IT_SCHEMA_BASE+'body',                     None                     )  body = matching_statements[0].object  print "*", bodydb.commit()

  在清單 4 中,首先從 issues.rdf 檔案中讀取(解除序列化)RDF;然後執行查詢以查詢表示指派給 uogbuji 哪些操作的語句。然後使用每個語句的主語(操作標識)來查詢每個操作的主體。如果安裝了 Python 和 4Suite,執行和下面相同的示例:

  $ python query1.pyActions assigned to uogbuji* Organize a vote on this topic* Correct all to use the "0/1" form in the next draft.

  這是 RDF 模型查詢的最底級別,因此有一點麻煩。清單 5 中的 Python 程式 query2.py 透過直接查詢相關主語和賓語等而走了一些捷徑。其結果就是清單 4 中同一個功能的更簡單的版本。

  清單 5:簡化查詢程式碼

   from Ft.Rdf import Util#Returns an RDF model object, and the database instance it uses for#persistence (in our case, it's just a memory data structure)model, db = Util.DeserializeFromUri('issues.rdf')db.begin()USER_ID_BASE = ''IT_SCHEMA_BASE = ''print 'Actions assigned to uogbuji:'actions = Util.GetSubjects(model, IT_SCHEMA_BASE+'assign-to',              USER_ID_BASE+'uogbuji')for action in actions:  body = Util.GetObject(model, action, IT_SCHEMA_BASE+'body')  print "*", bodydb.commit()

  清單 5 仍然包含兩種級別的查詢;使用結合多個查詢的單個請求將更方便和更有效。(透過使用“RDF 推論語言(RDF Inference Language (RIL))”,那也是可能的,“RDF 推論語言”將在本專欄的後續文章中討論。順便提一下,示例問題跟蹤器資料中參考了 RIL 開放規範草稿。)清單 6 演示了在使用或不使用 API 捷徑情況下,執行基本查詢的結果。

  清單 6:執行同清單 5 相同任務的簡化的查詢會話

  $ python query2.pyActions assigned to uogbuji* Organize a vote on this topic* Correct all to use the "0/1" form in the next draft.

  RDF 查詢不必涉及後設資料語句元件的精確匹配。大多數的查詢語言提供大量的靈活性。作為一個示例, 清單 7(query3.py)中的 Python 程式使用基於正規表示式的查詢來查詢所有指派給 uogbuji 的操作(該操作的主體包含字串“vote”)。

  同樣,透過使用 RIL,清單 7 中的程式碼將是一個簡單查詢而且更有效(將在下一篇專欄文章裡講述)。清單 8 演示了查詢中正規表示式的使用。

  清單 8:演示在查詢中使用正規表示式的會話

  $ python query3.pyActions assigned to uogbuji* Organize a vote on this topic

  下一次……

  本專欄文章演示瞭如何從示例問題跟蹤器應用程式將各部分組成完整的 RDF 模型,並且舉例說明了該模型的基本查詢。在下篇文章中將探討一種豐富特性,可以利用 RDF 的強大功能來低成本地利用該特性。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-950190/,如需轉載,請註明出處,否則將追究法律責任。

相關文章