Vincent.Chan‘s Blog

          常用鏈接

          統(tǒng)計

          積分與排名

          網(wǎng)站

          最新評論

          XML 觀察: 追溯 RDF 數(shù)據(jù)的源頭::RDF 工具正逐漸成熟起來

          級別: 中級

          Edd Dumbill, 編輯兼發(fā)行人, xmlhack.com

          2003 年 3 月 01 日

          當(dāng) 您開始聚集來自 Web 的數(shù)據(jù)時,了解其來源是至關(guān)重要的。本文中,Edd Dumbill 研究了 Redland 資源描述格式(Resource Description Format,RDF)應(yīng)用程序框架的上下文特性并創(chuàng)建了作為演示的一個 RDF Site Summary(RSS)1.0 聚集器。

          一年前,我為 developerWorks寫了兩篇有關(guān) 朋友的朋友(Friend-of-a-Friend,F(xiàn)OAF)項目的文章。FOAF 是一種 XML/RDF 詞匯表,用于以計算機可讀的形式描述您通常可以放在主 Web 頁上的某種個人信息,如您的姓名、即時信使昵稱和工作地點等。

          在我有關(guān) FOAF 的第二篇文章(請參閱 參考資料)的清單 6 中,我演示了 FOAFbot,一個我編寫的聚集人們的 FOAF 文件并回答相關(guān)問題的社區(qū)支持代理。FOAFbot 能夠記錄誰說了關(guān)于誰的什么事情。當(dāng)問及我叫什么名字時,F(xiàn)OAFbot 答道:

          												
          														
          edd@xml.com's name is 'Edd Dumbill',
          according to Dave Beckett, Edd Dumbill,
          Jo Walsh, Kip Hampton, Matt Biddulph,
          Dan Brickley, and anonymous source Anon47

          FOAFbot 背后的思想是,如果您能夠驗證不同的幾個人(您所信任的人)都記錄了一個事實,那么您很可能相信這是真實的。

          以 下是追溯這樣的元數(shù)據(jù)源頭的另一個運用。搜索引擎在其早期歷史中被濫用的一個主要表現(xiàn)是惡意元標(biāo)記(meta tag spamming)。網(wǎng)站會把錯誤的元數(shù)據(jù)放到它們的頁面中以提高它們的搜索引擎排名。由此,搜索引擎不再關(guān)注元標(biāo)記,因為它們極有可能提供虛假信息。事 實上,象 Google 這樣的搜索引擎找到了其它更高級的度量來評定頁面關(guān)聯(lián)性。

          展望 Web 的未來,避免諸如惡意元標(biāo)記這樣的濫用將變得至關(guān)重要。Tim Berners-Lee 對 Semantic Web 的展望(請參閱 參考資料)是希望出現(xiàn)這樣一個 Web:其上大多數(shù)的數(shù)據(jù)都是機器可讀的,從而使得目前由人類完成的大多數(shù)信息處理自動進行。

          元數(shù)據(jù)濫用在 Semantic Web 上可能造成的麻煩甚至更大:網(wǎng)站不再限于僅僅造自己站點的假。它還可以造其它站點的假。例如,一家書店對競爭者的報價作假,這是有可能的。

          我不會探究各種安全性和可信機制(這些機制將防止這種語義的破壞行為)的細(xì)節(jié),而是將重點討論這樣的機制之所以成為可能的基礎(chǔ): 追溯源頭

          存儲 RDF

          處理 RDF 然后存儲它的應(yīng)用程序使用 三元組存儲(triple store)來做到這一點。RDF/XML 輸入文檔被分解成一列包含 主語、謂語和賓語 的三元組。然后后續(xù)處理就是操作和查詢存儲中的三元組。只有在涉及到交換時,才會用 RDF 的 XML 語法。由于將數(shù)據(jù)直接分解成三元組,所以 XML 工具(象 XPath 或 XQuery)就沒有多少用處了。已經(jīng)有人編寫了直接使用 XQuery 操作 XML 語法的 RDF 處理工具,但我認(rèn)為對于通用的 RDF 處理,這多少有點多此一舉。

          為了進行演示,我將向您展示如何將簡單的 RSS 1.0 文檔用作測試數(shù)據(jù)。最近我建立了一個 weblog 站點,其中,我對不知情的公眾強加了我的觀點。為了將我涂鴉式的元數(shù)據(jù)放在一起,我生成了一個 RSS 1.0 文件(請參閱 參考資料獲取鏈接)。該文件的開始部分類似于清單 1,曾接觸過 RSS 的任何人應(yīng)該對它非常熟悉。


          清單 1. 摘自 RSS 1.0 文件的開始部分
          												<rdf:RDF
          xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
          xmlns:dc="http://purl.org/dc/elements/1.1/"
          xmlns="http://purl.org/rss/1.0/"
          >
          <channel rdf:about="http://usefulinc.com/edd/blog">
          <title>Edd Dumbill's Weblog: Behind the Times</title>

          <description>
          Thoughts and comment from Edd Dumbill, technology writer
          and free software hacker.
          </description>
          <link>http://usefulinc.com/edd/blog</link>

          在 RDF 處理器將這一部分解析成三元組時,我獲得了清單 2 中顯示的數(shù)據(jù)。


          清單 2. 與清單 1 的開始部分對應(yīng)的 RDF 三元組
          												[http://usefulinc.com/edd/blog,
          http://www.w3.org/1999/02/22-rdf-syntax-ns#type,
          http://purl.org/rss/1.0/channel]
          [http://usefulinc.com/edd/blog,
          http://purl.org/rss/1.0/title,
          "Edd Dumbill's Weblog: Behind the Times"]
          [http://usefulinc.com/edd/blog,
          http://purl.org/rss/1.0/description,
          "Thoughts and comment from Edd Dumbill,
          technology writer and free software hacker."]
          [http://usefulinc.com/edd/blog,
          http://purl.org/rss/1.0/link,
          "http://usefulinc.com/edd/blog"]

          隨后 RDF 應(yīng)用程序所要操作的就是 清單 2中顯示的這列三元組了。至此,一切都很順利。但在存儲這個數(shù)據(jù)時,您會丟失一些重要信息的線索,即數(shù)據(jù)的出處和其它相關(guān)數(shù)據(jù),如我是何時對數(shù)據(jù)拍了快照。要記錄這個信息,我需要通過一些方式使該信息與我所找到的 RDF 語句相關(guān)聯(lián)。

          首先,對于 清單 2中的數(shù)據(jù),我需要模擬出一個描述,記錄下對于這些數(shù)據(jù)我可能要說的內(nèi)容。清單 3 就包含了這樣一個示例描述,它使用了專為這一目的而虛構(gòu)出的一個示例名稱空間。


          清單 3. 檢索清單 1 和清單 2 中數(shù)據(jù)的示例描述
          												<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
          xmlns:me="http://example.org/ns/mymeta#">

          <rdf:Description rdf:about="http://example.org/retrieval/52365">
          <me:origin rdf:resource="http://usefulinc.com/edd/blog/rss" />
          <me:retrieved>2003-06-24T08:59:55.00Z</me:retrieved>
          </rdf:Description>
          </rdf:RDF>

          您可以從 清單 3中看出:我已經(jīng)(任意)虛構(gòu)了一個 URI 來表示對一個文件進行的第 52365 次檢索。這似乎是一個合理的方法,如同任何對遠程資源的每次輪詢所命名的那樣。這個資源的出處是這個 RSS 1.0 文件的 URI,而時間戳記表明何時找到它的。

          現(xiàn)在,剩下的就是存儲四元組,而不是存儲三元組。清單 4 展示了我如何修改 清單 2以顯示我現(xiàn)在添加到存儲中的所有數(shù)據(jù)。


          清單 4. 增加了上下文 URI 和上下文元數(shù)據(jù)的三元組
          												[http://usefulinc.com/edd/blog,
          http://www.w3.org/1999/02/22-rdf-syntax-ns#type,
          http://purl.org/rss/1.0/channel,
          http://example.org/retrieval/52365]
          [http://usefulinc.com/edd/blog,
          http://purl.org/rss/1.0/title,
          "Edd Dumbill's Weblog: Behind the Times",
          http://example.org/retrieval/52365]
          [http://usefulinc.com/edd/blog,
          http://purl.org/rss/1.0/description,
          "Thoughts and comment from Edd Dumbill,
          technology writer and free software hacker.",
          http://example.org/retrieval/52365]
          [http://usefulinc.com/edd/blog,
          http://purl.org/rss/1.0/link,
          "http://usefulinc.com/edd/blog",
          http://example.org/retrieval/52365]
          [http://example.org/retrieval/52365,
          http://example.org/ns/mymeta#origin,
          http://usefulinc.com/edd/blog/rss,
          <NULL>]
          [http://example.org/retrieval/52365,
          http://example.org/ns/mymeta#retrieved,
          "2003-06-24T08:59:55.00Z",
          <NULL>]

          清單 4中演示的思想是每個 RDF 語句都增加了一個 URI,它將該 RDF 語句鏈接到我想要存儲的有關(guān)該 RDF 語句的元數(shù)據(jù)上。這個簡單機制給我?guī)砹藷o窮的力量。除了使我能夠檢索有關(guān)該 RSS 文件的元數(shù)據(jù)以外,它還提供了從存儲中除去該信息的便利方法。





          回頁首


          實際實現(xiàn)

          在運用這個思想時,我已將上面四元組的第四個元素稱為 上下文。這個術(shù)語并不規(guī)范,但它對我而言非常有效。而且,Redland RDF 應(yīng)用程序框架中也使用了這個術(shù)語,我將使用該框架來演示這個追溯源頭的應(yīng)用程序。

          (順 便提一下,我要對 Dave Beckett(Redland 的創(chuàng)建者)表示感謝。在我去年編寫 FOAFbot 時,Redland 不支持上下文,所以我最終只能以一種非常繁冗的格式來實現(xiàn)上下文。Dave 回應(yīng)了我的請求,他將上下文的支持添加到了他的工具箱中。)

          Redland 是一個基于 C 的工具箱,帶有許多語言綁定,包括 Python、Perl 和 Java。它由一個 RDF 解析器、raptor 和一個數(shù)據(jù)存儲組成。該存儲目前使用 Berkeley DB 文件,不過還在開發(fā)對底層 SQL 存儲的支持。對于我的示例而言,我將使用到 Redland 的 Python 綁定。

          這里的目標(biāo)是要創(chuàng)建一個簡單的 RSS 1.0 聚集器。使用聚集器的目的是對多個 RSS 饋送進行重復(fù)拍快照,并允許您以有趣的方式組合它們。隨著新內(nèi)容項的加入,RSS 文件會隨著時間的變化而發(fā)生更改 - 我想避免多個冗余項,而仍能保留歷史項。在本文后面,我將開發(fā)所需的一些功能。

          您將在 參考資料中找到一個到這個項目的 Python 代碼(fraggle.tar.gz)的鏈接。還有一個到 Redland 工具箱的鏈接,您也需要安裝這個工具箱。

          Aggregator 類會處理訪存和存儲 RDF 數(shù)據(jù)這個有趣的工作。清單 5 摘自這個類的 load_uri 方法,它從 aggregate.py 的第 189 行開始。


          清單 5. 追溯檢索到的 RDF 的上下文
          												stream = self._parser.parse_as_stream(
          RDF.Uri(string="file:./%s" % fname),
          base_uri=urinode.uri)
          if stream:
          channel = None

          context = self.context_uri_node()
          timestamp = RDF.Node(literal=
          time.strftime("%Y-%m-%dT%H:%M:%S.00Z"))
          while not stream.end():
          statement = stream.current()
          # add the statement to the model, with context

          self._model.add_statement(statement, context)

          # if it's a <rss:channel> remember the URI
          if ( statement.predicate == _rdfType and
          statement.object == _rssChannel ):
          channel = RDF.Node(node=statement.subject)

          # move on
          stream.next()

          # now to add the context information
          # first, the source URI

          self._model.add_statement(RDF.Statement(
          subject=context, predicate=_fraggieSource,
          object=urinode), _globalContext)

          # second, the channel URI

          self._model.add_statement(RDF.Statement(
          subject=context, predicate=_fraggieChannel,
          object=channel), _globalContext)

          # third, the timestamp

          self._model.add_statement(RDF.Statement(
          subject=context, predicate=_fraggieTimestamp,
          object=timestamp), _globalContext)

          # fourth, the checksum

          self._model.add_statement(RDF.Statement(
          subject=context, predicate=_fraggieChecksum,
          object=RDF.Node(literal=checksum)), _globalContext)
          self.register_fetch(urinode, context)



          該清單中用粗體顯示的幾行與追溯上下文有關(guān)。首先,使用 context_uri_node() 生成上下文的 URI。這返回形式為 http://usefulinc.com/fraggie/global/1 的 URI 結(jié)果。這個上下文然后被追加到在檢索到的 RSS 中找到的每個語句中。一旦存儲了 RSS 數(shù)據(jù),我隨后就將有關(guān)上下文 URI 的數(shù)據(jù)添加到存儲中。在本例中,我存儲了作為 RSS 文件來源的 URI、RSS 通道本身的 URI( rss:channel 元素中的 rdf:about 值)、訪存文件的時間以及文件的 MD5 校驗和(以便以后確定 RSS 文件是否隨時間變化而發(fā)生了更改)。

          如果您下載了源代碼,那么正如您將看到的, Aggregator 類的其余部分實現(xiàn)了兩個功能:第一個是 RSS 搜索所需的內(nèi)務(wù)處理方法;第二個向聚集器的詢問者提供了查詢方法。請注意,所有的內(nèi)務(wù)處理變量(如 fetch 計數(shù))都是用 RDF 表示的,并且保存在 RDF 存儲中。清單 6 展示了將計數(shù)變量表示為 RDF/XML 語句。


          清單 6. 用 RDF 表示的內(nèi)部計數(shù)器
          												<rdf:Description
          rdf:about="http://usefulinc.com/fraggie/counter"
          rdf:value="0" />

          我發(fā)現(xiàn)在 RDF 存儲中持久地保存任何擁有全局作用域的變量是很有意義的。這種方法的一個直接優(yōu)點是它在多次調(diào)用后仍能保持狀態(tài)。

          該演示歸檔文件包括兩個您可以運行的示例 RSS 文件。使用 python fraggle.py 可以調(diào)用該演示。該演示首先使聚集器裝入這兩個示例 RSS 文件,它們都引用了 Mark Pilgrim 最近在 XML.com 上發(fā)表的一篇文章。這個練習(xí)的目的是找到誰對這篇文章作了什么評價。運行該演示產(chǎn)生的輸出如清單 7 所示(為可讀性起見,已對一些輸出行重新進行了格式處理)。


          清單 7. fraggle.py 的輸出
          												Links to http://www.xml.com/pub/a/2003/07/02/dive.html

          From : Meerkat: An Open Wire Service: XML.com
          <http://meerkat.oreillynet.com/>
          Time : 2003-07-05T15:39:26.00Z
          Title: The Vanishing Image: XHTML 2 Migration Issues
          Desc : In Mark Pilgrim's latest Dive Into XML column,
          Pilgrim examines XHTML 2.0 <tt>object</tt>
          element, which is a replacement for the more
          familiar and widely supported <tt>img</tt>.

          From : paranoidfish.org/links
          <http://www.paranoidfish.org/links/>
          Time : 2003-07-05T15:39:25.00Z
          Title: XML.com: The Vanishing Image: XHTML 2 Migration
          Issues [Jul. 02, 2003]
          Desc : using <object> as a replacement for <img>
          is not a safe bet right now

          摘自 XML.com 的第一部分展示了對這篇文章的正式描述。第二部分摘錄展示了由 paranoidfish.org 網(wǎng)站所有者提供的摘要。

          如果您研究過 fraggle.py 的源代碼,那么將明白所有查詢都圍繞上下文進行。首先,會詢問聚集器哪些上下文提到了這篇文章的 URI。然后根據(jù)上下文請求文章元數(shù)據(jù)并建立索引。請注意,上下文在時間上對應(yīng)于一個饋送的快照。如果我的示例隨時間變化要獲得更多 RSS 文件的快照,那么您可能會看到有幾項都是來自同一來源的 - 可能在描述上稍作了更改(人們常常會隨時修正拼寫錯誤)。對 fraggle.py 中查詢的一個明顯改進是根據(jù)源進行分組,而不是單單根據(jù)時間順序進行顯示。

          盡 管從瀏覽、自我沖浪(ego-surfing)的角度而言,weblog 和其它因特網(wǎng)站點的 RSS 饋送很有趣,但我認(rèn)為象這樣一個項目的真正價值很有可能體現(xiàn)在企業(yè)中。許多組織常常會生成大量以時間為序的數(shù)據(jù)流。舉一個簡單的示例,URI 分配給了客戶或項目,然后就可以生成并聚集活動的 RSS 流。

          然后可以很輕松的為那些對這樣的聚集數(shù)據(jù)感興趣 的任何人劃分和切割這些數(shù)據(jù)。例如,管理者可能希望知道每個工人在做什么,項目經(jīng)理可能希望獲得最近的三個狀態(tài)更新,更高級的管理層可能希望獲得整個部門 的快照視圖,等等。不難想象,這種工具很可能會在客戶關(guān)系管理(CRM)這一領(lǐng)域中產(chǎn)生最佳收益。





          回頁首


          結(jié)束語

          本文中演示的簡單示例只觸及了追溯 RDF 源頭的皮毛。在 Web 上,信息來自哪里與信息本身同樣重要。源頭追溯的 RDF 工具剛開始興起,當(dāng)它們的使用變得更廣泛時,它們的能力無疑會更加完善。

          毫無疑問,Redland RDF 應(yīng)用程序框架是一個值得進一步研究的工具箱。它具有到您最喜愛的腳本編制語言的接口;它運行在 UNIX、Windows 和 Mac OS X 上;而且它是一個開放源碼項目,所以您所做的任何改進會使整個社區(qū)受益。





          回頁首


          參考資料





          回頁首


          關(guān)于作者


          Edd Dumbill 是 XML.com的執(zhí)行編輯以及 XML 開發(fā)人員新聞?wù)军c XMLhack的編輯和發(fā)行人。他是 Programming Web Services with XML-RPC一書的合著者,以及 Pharmalicensing生命科學(xué)知識產(chǎn)權(quán)交易事務(wù)所的共同創(chuàng)始人和顧問。Edd 還是 每年一度的 XML 歐洲大會的議程主席。您可以通過 edd@xml.com與 Edd 聯(lián)系。

          posted on 2006-03-18 21:26 Vincent.Chen 閱讀(507) 評論(0)  編輯  收藏 所屬分類: AJAX

          主站蜘蛛池模板: 唐山市| 鄱阳县| 喀喇沁旗| 咸丰县| 垦利县| 抚宁县| 湘潭市| 高雄市| 察哈| 耒阳市| 启东市| 翁源县| 江达县| 巴林左旗| 金山区| 云霄县| 广昌县| 固阳县| 吉林市| 江源县| 石泉县| 辉县市| 陵川县| 黎平县| 当涂县| 湟中县| 即墨市| 渭南市| 舒城县| 达孜县| 界首市| 昂仁县| 榆社县| 莲花县| 高州市| 永胜县| 镇安县| 秦安县| 河北省| 乌拉特前旗| 东乌|