今天的Web主要是面向人類的使用而建立的。即使Web上已經開始出現機器可讀的資料,它們通常僅僅是將資料和格式分存在獨立的文件中,並且在面向人類和面向機器的版本中保留非常有限的對應。結果,Web瀏覽器在解析和處理Web資料時僅能向人類提供最小的輔助:瀏覽器僅僅理解關於如何去顯示的資訊。我們引入RDFa來提供一個XHTML的屬性集合,用來爲視覺化資料增加機器可讀的資訊。我們將介紹如何使用RDFa來表達簡單的和複雜的資料集,特別是如何在不重復內容的同時將現有的人類可見的文本與鏈結轉換爲機器可讀的資料。
本文檔僅作爲RDFa入門。RDFa的正式規範可以在[RDFA-SYNTAX]中找到。
本節描述本文檔在其發表時的狀態。其他文檔可以取代本文檔。當前W3C出版物的列表和本技術報告的最新版本可以參見位於http://www.w3.org/TR/的W3C技術報告索引。
本文檔是一份由W3C語義Web部署工作組 [SWD-WG]和W3C XHTML2工作組 [XHTML2-WG]聯合創作的工作組記錄。這項工作是W3C語義Web行動和HTML行動的一部分。在本文檔轉換爲工作組記錄的同時,RDFa語法規範轉換爲了W3C推薦標準。
RDFa入門的這個版本包括了對前一個版本的少許編輯上的修改,並增加了簡短的一節(4.1)爲那些希望創建新的關係辭彙表的人們提供指南。所有的修改在差異文檔中詳細敍述。工作組已經收到了擴展本文檔的建議,並且工作組可能在未來增加內容,但並不承諾會這麽做。
歡迎將對這份工作組記錄的意見建議發送到public-rdf-in-xhtml-tf@w3.org;請在郵件主題中加入"comment"字樣。這個郵件地址收到的所有郵件在公共檔案中可以查看。
作爲工作組記錄發表並不意味著被W3C全體成員認可。這是一個草案並可能在任何時刻被更新、替換或廢止。本文檔被引用的唯一合適方式是作爲正進行中的工作。
本文檔是由根據2004年2月5日發佈的W3C專利政策來運作的團隊制定的。W3C維護著一個與XHTML 2工作組的交付産品有關的已公開的專利列表,以及另一個與語義Web部署工作組的交付産品有關的已公開的專利列表;這些頁面中也包括如何公開一項專利的說明。一個對專利擁有實際知識並相信該專利包含了基本要求的個人必須根據W3C專利政策第6節的要求公開這個資訊。
1 引言
1.1 HTML vs. XHTML
2 給XHTML加點調料
2.1 爲你的作品指定許可協定
2.2 對題目和作者加標簽
2.3 一頁多項
3 更進一步
3.1 聯繫資訊
3.2 社會網路
4 關於RDF
4.1 自定義辭彙表
5 瞭解更多
6 致謝
7 參考文獻
Web是一個豐富的分散式的互聯資訊倉庫,這些資訊主要是面向人類的使用組織起來的。在一張典型的網頁上,一個XHTML作者可能指定了一個標題,接下來用小字型大小寫了一個子標題、一塊斜體的文本、幾段中等字型大小的文本,最後寫了幾個帶超鏈結的單詞。Web瀏覽器將切實遵守這些顯示指令。然而,只有人類思維可以理解那個標題事實上是博文的題目,子標題是作者,斜體文本是文章的發表日期,而帶超鏈結的單詞是分類標簽。程式與人類理解之間存在很大的鴻溝。
![]() |
如果瀏覽器從網頁的視覺化元素中接收到了關於其內在含義的資訊會怎麽樣呢?一個在博客中宣佈的宴會可以很容易地被拷貝到用戶的日程表中,而作者的完整聯繫方式同樣可以很容易地被拷貝到用戶的地址簿中。用戶可以根據分類標簽(通常稱作tag)自動地回訪以前瀏覽過的文章。一張從網站上拷貝並粘貼到學校報告中的照片可以附帶一個鏈回到攝影師的鏈結,並給與她合適的稱讚以感謝知識産權。當原先爲人類準備的Web資料被擴展爲也能爲電腦程式的處理提供便利時,這些程式將很明顯地變得更有幫助,因爲它們開始理解資料的結構了。
RDFa正允許XHTML作者這麽做。使用一些簡單的XHTML屬性,作者能夠用機器可讀的指示符來標記人類可讀的資料以便於瀏覽器和其他程式去解釋。一張網頁爲各專案能夠包括的標記可以像文章的題目那麽簡單,也可以像用戶的完整社會網路那麽複雜。
RDFa得益於RDF [RDF]的廣泛能力——RDF是W3C爲可互操作的機器可讀數據建立的規範。當然,本文的讀者們並不被要求去理解RDF。但讀者們需要對XHTML有一個基本瞭解。
比如說Alice——一個在http://example.com/alice
上既發佈了專業文章又發佈了個人文章的博客。我們將構造樣例標記來演示Alice可以如何使用RDFa。這些樣例的完整標記可以獨立地在此閱讀。
在她博客的頁腳,Alice聲明她的博客內容可以自由地被重用——只要在她的文章被引用時給予她應有的稱讚就行了。在這個博客頁面的XHTML中包括了一個指向Creative Commons [CC]許可協定的鏈結:
... All content on this site is licensed under <a href="http://creativecommons.org/licenses/by/3.0/"> a Creative Commons License </a>.
一個人可以清楚地理解這個句子的意思,特別是其中的鏈結相對于當前文檔的含義:它指出了文檔的許可協定——即在什麽條件下頁面的內容可以被分發。不幸的是,當Bob訪問Alice的博客時,他的瀏覽器只能明白這兒有一個普通的鏈結——可能指向Alice的一個朋友,也可能指向她的個人簡歷。爲了讓Bob的瀏覽器理解這個鏈結實際上是指向文檔的許可協定條款,Alice需要增加一些調料來提示這個鏈結是什麽類型的。
她可以使用rel
屬性來增加這個調料(我們將簡寫爲@rel
來避免經常重復“屬性”這個詞),它定義了當前頁面與鏈結到的頁面之間的關係。這個屬性的值是license
——一個在XHTML中恰爲這個目的保留的關鍵字:
...
All content on this site is licensed under
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/">
a Creative Commons License
</a>.
有了這樣微小的升級,Bob的瀏覽器現在可以理解這個鏈結有了點調料:它指向這個博客的許可協定。
![]() |
Alice很高興,因爲她爲XHTML增加調料後使得Bob很容易地找到了她博客的許可協定。但是文章的題目和作者的姓名怎麽辦?現在,Alice並不是要去標記一個鏈結,而是要擴展頁面中的文本。文章的題目就是頁面的標題,而她的姓名就是子標題:
<div> <h2>The trouble with Bob</h2> <h3>Alice</h3> ... </div>
爲了表明h2
代表頁面的標題而h3
代表作者,Alice用@property
這個RDFa中引入的屬性來特別地標記XHTML頁面中的文本。
<div xmlns:dc="http://purl.org/dc/elements/1.1/"> <h2 property="dc:title">The trouble with Bob</h2> <h3 property="dc:creator">Alice</h3> ... </div>
爲什麽要用dc:creator
和dc:title
而不簡單地用creator
和title
呢?這是因爲XHTML並沒有爲這兩個概念保留關鍵字。儘管Alice可以大膽地寫成property="title"
,但一個程式讀到這裏如何才能知道這裏的“title”到底是指一件作品的題目、一門職業的名稱還是什麽房産契約呢?並且,如果每個Web發佈者都使用他們自己的短關鍵字作爲屬性,那麽所有可用的屬性構成的世界將變得相當混亂,就有點像在電腦中把每個文件都直接存在桌面上而不使用任何目錄結構去組織它們。
爲了進行一定程度的組織,RDFa並不去識別property="title"
。Alice必須用一個URL來指明Web上的一個目錄,從那兒導入她想要表達的特定的creator
和title
概念。幸運地是,Dublin Core [DC]社區已經爲描述文檔時會用到的概念定義了一個辭彙表,其中就包括creator
和title
,並且title
就是指一件作品的題目。因此,Alice就:
xmlns:dc="http://purl.org/dc/elements/1.1/"
導入了Dublin Core辭彙表,將字首dc
和http://purl.org/dc/elements/1.1/
這個URL關聯了起來,並且dc:creator
和dc:title
。它們分別是http://purl.org/dc/elements/1.1/creator
和http://purl.org/dc/elements/1.1/title
這兩個URL的縮寫。在RDFa中,事實上所有的屬性名稱都是URL。
![]() |
Alice的博客當然包括不止一篇博文。有時候Alice的姐妹Eve也會來客串寫幾篇。博客的頭版列出了10篇最近的博文,每一篇顯示了它的題目、作者和第一段。那麽,當這些博文出現在一張網頁上時,Alice應該怎樣爲它們分別標記題目呢?RDFa提供了@about
屬性來指定其中的RDFa標記應該作用於哪個URL:
<div xmlns:dc="http://purl.org/dc/elements/1.1/"> <div about="/alice/posts/trouble_with_bob"> <h2 property="dc:title">The trouble with Bob</h2> <h3 property="dc:creator">Alice</h3> ... </div> <div about="/alice/posts/jos_barbecue"> <h2 property="dc:title">Jo's Barbecue</h2> <h3 property="dc:creator">Eve</h3> ... </div> ... </div>
讓我們再一次用示意圖表示——把URL連到屬性上:
![]() |
當Alice在博客中貼上了他的好朋友Bob拍的照片時,她可以用同樣的方法去給他合適的稱讚以感謝知識産權:
<div about="/alice/posts/trouble_with_bob"> <h2 property="dc:title">The trouble with Bob</h2> The trouble with Bob is that he takes much better photos than I do: <div about="http://example.com/bob/photos/sunset.jpg"> <img src="http://example.com/bob/photos/sunset.jpg" /> <span property="dc:title">Beautiful Sunset</span> by <span property="dc:creator">Bob</span>. </div> </div>
注意最內層的@about
屬性值http://example.com/bob/photos/sunset.jpg
是怎樣對最內層的div
內的所有標記“隱藏”了外層的@about
屬性值/alice/posts/trouble_with_bob
的。再一次用示意圖來抽象地表示這部分新的標記背後的資料:
![]() |
Alice還想要讓她自己的一些資訊(比如電子郵件地址、電話號碼等)容易地被她朋友的聯繫資訊管理軟體所獲取。這回就不再是描述一張網頁的屬性了,而是要描述她自己這樣一個人的屬性。因此,她增加了更深的結構使得她能夠把多個具有各自屬性的項連起來。
Alice已經在她的博客上顯示了她的聯繫資訊。
<div> <p> Alice Birpemswick </p> <p> Email: <a href="mailto:alice@example.com">alice@example.com</a> </p> <p> Phone: <a href="tel:+1-617-555-7332">+1 617.555.7332</a> </p> </div>
Dublin Core辭彙表並沒有提供用來描述聯繫資訊的屬性名稱,但Friend-of-a-Friend [FOAF]辭彙表提供了。在RDFa中,很經常也很容易在一個頁面中組合使用不同的辭彙表。現在Alice要導入FOAF辭彙表並聲明一個foaf:Person
的實例。因此,Alice使用了@typeof
這個RDFa屬性,這個屬性專門用來聲明一個具有特定類型的資料項目:
<div typeof="foaf:Person" xmlns:foaf="http://xmlns.com/foaf/0.1/">
...
接下來,Alice可以指明頁面上的哪些內容表示她的全名、電子郵件地址和電話號碼:
<div typeof="foaf:Person" xmlns:foaf="http://xmlns.com/foaf/0.1/"> <p property="foaf:name"> Alice Birpemswick </p> <p> Email: <a rel="foaf:mbox" href="mailto:alice@example.com">alice@example.com</a> </p> <p> Phone: <a rel="foaf:phone" href="tel:+1-617-555-7332">+1 617.555.7332</a> </p> </div>
注意Alice是怎樣沒有像她此前增加博文元資料時那樣去指定@about
的。那麽,她正把這些屬性關聯到什麽東西上面呢?事實上,div
中的@typeof
隱式地設定了div
內標記的那些屬性的主語。姓名、電子郵件地址和電話號碼都關聯到一個類型爲foaf:Person
的新的節點。這個節點沒有任何URL來標識,所以被稱作空白節點。
![]() |
接下來,Alice想要增加一些她好朋友的資訊,至少包括他們的姓名和主頁。普通的XHTML寫法是:
<div> <ul> <li> <a href="http://example.com/bob/">Bob</a> </li> <li> <a href="http://example.com/eve/">Eve</a> </li> <li> <a href="http://example.com/manu/">Manu</a> </li> </ul> </div>
首先,Alice指明所有這些朋友的類型都是foaf:Person
。
<div xmlns:foaf="http://xmlns.com/foaf/0.1/"> <ul> <li typeof="foaf:Person"> <a href="http://example.com/bob/">Bob</a> </li> <li typeof="foaf:Person"> <a href="http://example.com/eve/">Eve</a> </li> <li typeof="foaf:Person"> <a href="http://example.com/manu/">Manu</a> </li> </ul> </div>
除了聲明資料的類型以外,每個@typeof
都會創建一個新的有著自己獨有屬性的空白節點,因而這些節點都不需要URL來標識了。例如,Alice很容易地指明了每個朋友的主頁(顯然主頁地址是一個人的獨有屬性,因此可以用來唯一地確定一個人):
<div xmlns:foaf="http://xmlns.com/foaf/0.1/"> <ul> <li typeof="foaf:Person"> <a rel="foaf:homepage" href="http://example.com/bob/">Bob</a> </li> <li typeof="foaf:Person"> <a rel="foaf:homepage" href="http://example.com/eve/">Eve</a> </li> <li typeof="foaf:Person"> <a rel="foaf:homepage" href="http://example.com/manu/">Manu</a> </li> </ul> </div>
當然,還有每個朋友的姓名:
<div xmlns:foaf="http://xmlns.com/foaf/0.1/"> <ul> <li typeof="foaf:Person"> <a property="foaf:name" rel="foaf:homepage" href="http://example.com/bob/">Bob</a> </li> <li typeof="foaf:Person"> <a property="foaf:name" rel="foaf:homepage" href="http://example.com/eve/">Eve</a> </li> <li typeof="foaf:Person"> <a property="foaf:name" rel="foaf:homepage" href="http://example.com/manu/">Manu</a> </li> </ul> </div>
Alice用@property
來表明那些鏈結上的文本("Bob"、"Eve"和"Manu")事實上是她朋友們的姓名。通過@rel
來表明那些可以點擊的鏈結將鏈到她朋友們的主頁。Alice很高興只用了這麽一點額外的標記就能夠完全地描述一個既讓人看起來舒服的頁面同時又是一個機器可讀的資料集。
此前,Alice對於重復地在每個新的社會網路站點上輸入她朋友的資訊已經感到厭倦了。而有了RDFa,她只需要在她自己的網頁上指出她的朋友圈子,而讓那些社會網路應用程式去自動地讀取這些資訊。目前爲止,Alice已經列上去了三個人,但還沒有指明她與他們之間的關係;他們可能是她的朋友,也可能是她最喜歡的17世紀的詩人。爲了表明實際上她是認識他們的,她用了FOAF辭彙表中的foaf:knows
屬性:
<div xmlns:foaf="http://xmlns.com/foaf/0.1/" about="#me" rel="foaf:knows">
<ul>
<li typeof="foaf:Person">
<a property="foaf:name" rel="foaf:homepage" href="http://example.com/bob">Bob</a>
</li>
<li typeof="foaf:Person">
<a property="foaf:name" rel="foaf:homepage" href="http://example.com/eve">Eve</a>
</li>
<li typeof="foaf:Person">
<a property="foaf:name" rel="foaf:homepage" href="http://example.com/manu">Manu</a>
</li>
</ul>
</div>
只要用一次rel="foaf:knows"
就足以把Bob、Eve和Manu都連到Alice了。能做到這樣是因爲RDFa中鏈式的概念:因爲頂層的@rel
並沒有相應的@href
,所以它將連到任何它所包含的節點,在這裏就是被@typeof
定義的三個節點。(@about="#me"
是一種FOAF/RDF約定:代表Alice這個人的URL是http://example.com/alice#me
。它不應當與Alice的主頁http://example.com/alice
混淆。你這個人肯定不能與你的主頁等同起來。)
![]() |
RDF,即資源描述框架,正是我們在上述例子中抽取出的圖結構的抽象資料表示。圖中的每個箭頭被表示爲一個“主語-謂語-賓語”形式的三元組:主語是箭頭的起始節點,謂語是箭頭本身,賓語是箭頭的終止節點或是一個字面量。一個RDF資料集通常稱作一個“RDF圖”,並且一般存儲在一個所謂“三元組記憶體”中。
比如說第一個示例圖:
![]() |
這個圖中的兩個RDF三元組用Notation3語法 [N3]書寫如下:
<http://www.example.com/alice/posts/trouble_with_bob> <http://purl.org/dc/elements/1.1/title> "The Trouble with Bob"; <http://purl.org/dc/elements/1.1/creator> "Alice" .
同樣地,我們畫出來的TYPE
箭頭與其他箭頭沒什麽不同,只不過它們的標簽實際上是一個核心的RDF屬性——rdf:type
,這裏rdf
命名空間是指<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
。上述聯繫資訊的例子因此應該這樣表示成RDF圖:
![]() |
RDF的定位是爲描述資料提供一個通用的語言。一個資料單元可以有任意多的域,域的名稱是那些可以被任何資料發佈者重用的URL,正如任何Web開發者都可以連接到任何網頁,即使並不是他們自己創建的。有了來源不同的RDF三元組形式的資料,並使用RDF查詢語言SPARQL [SPARQL],人們可以搜索“Alice的那些創建了題目包含'Bob'的項的朋友們”,不論那些項是博文、視頻、日程表事件或者其他我們還不知道的資料類型。
RDF是一種抽象的、機器可讀的資料表示,用來最大程度地實現辭彙表的重用。RDFa是一種在XHTML中通過重用已有的人類可讀的資料來描述RDF資料的方法。
Alice已經用RDFa標記了她的頁面,接下來她可能又會發現需要去描述一些資料,例如她最喜歡的照片,而要描述這些資料,現有的Dublin Core或者FOAF等辭彙表是不夠的。既然RDFa不過是RDF的一種表示形式,支援RDF可擴展性的RDF模式機制同樣也可以支援RDFa的可擴展性。一旦一個RDF辭彙表被創建了,它就可以像現有的辭彙表一樣被用在RDFa標記中。
RDF入門[RDF-SCHEMA-PRIMER]的第5節介紹了如何去創建一個RDF模式。籠統一點說,爲RDFa創建一個RDF模式包括:
http://example.com/photos/vocab#
。Photo
和Camera
,以及屬性takenWith
來把一張照片關聯到拍攝這張照片的照相機上。xmlns:photo="http://example.com/photos/vocab#"
以及typeof="photo:Camera"
。需要注意的是,任何人只要能在Web上發佈一個文檔就同樣能夠發佈一個RDF辭彙表並定義他們想要描述的新的資料欄。RDF和RDFa允許辭彙表以完全分散式的形式被擴展。
更多的例子、工具以及相關資訊可以在RDFa維基中找到。
本文檔是RDF-in-HTML工作組的工作,包括(按字母順序)Ben Adida、Mark Birbeck、Jeremy Carroll、Michael Hausenblas、Shane McCarron、Steven Pemberton、Manu Sporny、Ralph Swick和Elias Torres。這項工作的完成得益于以下人員的幫助:語義部署工作組以及它的前身語義Web部署和最佳實踐工作組,特別是Tom Baker和Guus Schreiber主席(以及前任主席David Wood);XHTML2工作組;語義Web行動的前任領導Eric Miller;以及語義Web行動的現任領導Ivan Herman。本文檔的早期版本由Gary Ng和David Booth進行了正式審閱,更早的版本由Diego Berrueta和Ed Summers審閱,他們都提出了深刻的意見,對這項工作有極大的促進作用。Bob DuCharme也審閱了這項工作並提供了有用的意見。