程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用Java技術將Atom轉換為RDF

使用Java技術將Atom轉換為RDF

編輯:關於JAVA

RDF 包含由 W3C 制定的各種規范。它本質上是一個元數據建模框架,該框架利用 Web 上分布的軟件可讀信息,具體方法是通過使用一些稱為三元組 的 “主語-謂語-賓語”表達式識別這些信息。

常用縮略詞

API:應用程序編程接口

RDF:資源描述框架

DOM:文檔對象模型

IETF:互聯網工程任務組

RSS:簡易新聞聚合

URI:統一資源標識符

URL:統一資源定位器

W3C:世界萬維網聯盟

XML:可擴展標記語言

例如下面這個英文表達式:“Perry the Platypus's arch-enemy is Dr. Doofenschmirtz.”。 在這個例子中,主語是 Perry the Platypus,謂語是 archenemy,賓語是 Dr. Doofenschmirtz。在 RDF 中,這個三元組將根據一種特殊格式編碼,這種格式用於識別卡通人物和他們的主要敵人。

RDF 代表 “明天”,因為它是 Semantic Web(語義 Web)運動的一部分。實際上,它是該運動的重要組成部分。

Semantic Web 運動代表下一代萬維網,其中的信息將通過語義識別。其理念是基於一種預定義格式顯示數據,這些數據可以被軟件和人類明確識別。想想看,這種預定義格式將使用 RDF 完成。(對 RDF 的詳細分析超出了本文的范圍,請參閱 參考資料 提供的鏈接了解更多信息)。

Atom:歡迎回到昨天

這部分的標題似乎對 Atom 不屑一顧,但事實上並非如此。相反,它意味著一種新出現的技術(RDF)和一種已經存在一段時間的技術(Atom)的對比。

Atom 是一系列基於 Web 的文檔的聚合格式,它從 RSS 的固有限制開發而來。這種聚合格式通過 XML 語言表達,所以 Atom 文檔即 XML 文檔。

通常,Atom 文檔通過一種稱為提要閱讀器(feed reader)的軟件閱讀,這種軟件使用戶能夠查看來自一個特定站點的一些相關文檔的摘要。用戶可以決定要閱讀哪些文件,然後只需單擊相應的鏈接。這種 Atom 聚合格式還允許網絡管理員顯示站點上的提要。

但是,Atom 沒有像新出現的 Semantic Web 活動那樣定義便於理解的語義。為此,需要使用 RDF。

兩個世界的精華

這樣,問題來了:“有沒有一種 RDF 規范能夠利用聚合?能不能既享受語義的好處,同時又保留高曝光度的優勢?”

答案是肯定的。

請走進 “另一個” RSS。這個 RSS 不是您所想到的那個 RSS,它表示 RDF Site Summary(RDF 站點摘要),以語義方式定義一種聚合格式。它允許網絡管理員以 RDF 格式發布他們的文檔,以便這些文檔中包含的信息能夠被 Semantic Web 所理解。

以 RDF 格式提供 feed 的好處在於:支持 Semantic Web 行為的資源將在其搜索結果中閱讀、緩存和包含來自那些源的內容。隨著 Semantic Web 不斷湧現,那些采用 RDF Site Syndication(RDF 站點聚合)技術的網絡管理員將發現自己置身於最新的、最先進的技術的最前沿。他們將擁有更高的曝光度,那意味著更多流量。更多流量意味著他們的廣告商將給用戶留下更深的印象。更深的印象意味著他們可以賺到更多錢。這肯定是一種值得投資的開發工作。

將 Atom 轉換為 RDF

既然這種格式轉換能夠帶來良好的經濟效益,那麼就讓我們著手進行這項工作吧。本文將介紹如何使用 Java 編程語言將 Atom 文檔轉換為 RDF 文檔。

幸運的是,Atom 和 RDF 文檔都是 XML 文檔,這意味著用於讀取一種文檔的工具將能夠用於讀取另一種文檔。

Java 編程語言

您將使用 1.6 版 Java 編程語言編寫轉換代碼。之所以選擇這種語言,是因為它著名的 “一次編寫到處運行” 的功能。您可以在擁有兼容 1.6 版 Java 軟件開發工具箱(JDK)的任意平台上編譯和運行本文提供的代碼。

解析和創建 XML 文檔的 API 是 Streaming API for XML (StAX),這是一個出色的界面,勝過了傳統的 DOM 和 Simple API for XML (SAX) 解析方案。使用 StAX 時,XML 文檔的解析是基於光標的,應用程序在運行過程中只使用 XML 中需要的內容。StAX 還允許開發人員創建 XML 文檔。

元數據

元數據本質上是關於數據的數據,它在 Semantic Web 中的作用非常關鍵。它提供前面提到的三元組的識別和解釋方法。

如前所述,您將對終端產品使用 RDF Site Syndication 規范。對於實現格式轉換這個目的,這種規范簡直堪稱完美,因為它是一種遵守 Semantic Web 的聚合格式。

必須再次提起注意的是,RDF Site Syndication 格式是一種獨立的規范,但它缺乏某些定義,比如日期。為了彌補這個缺陷,通常使用另一種 RDF 兼容規范,這種規范稱為 Dublin Core Metadata Initiative (DCMI)。DCMI 是與 RDF 聯用的最流行的 XML 語言之一。

編寫代碼

基本的思路是:先讀取一個現有的 Atom 提要,然後將這個提要轉換為 RDF。在這種情況下,需要將 Atom 格式的 Twitter public timeline 轉換為 RDF Site Syndication 格式。為此,應使用標准 JavaBeans™ 來存儲從 Atom 提要中讀取的信息。您也許知道,JavaBeans 是包含一系列私有屬性以及公共訪問器和轉變器的 Java 類。您可以使用這些類的內容來創建 RDF 文檔。

一個 RDF Site Syndication 文檔中包含兩個重要的 “節”。一個是 <channel> 節,另一個是 <item> 節,後者可能會多次出現。<channel> 節描述整個提要,每個 <item> 節描述這個提要中的一個文檔。清單 1 顯示了一個 RDF Site Syndication 文檔示例。

清單 1. RDF 文檔示例(節選)

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns="http://purl.org/rss/1.0/"
 xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel rdf:about="http://www.twitter.com">
     <title>Twitter public timeline</title>
     <description>Twitter updates from everyone!</description>
     <link>http://twitter.com/public_timeline</link>
     <dc:date>2009-04-05T13:11:01+00:00</dc:date>
     <items>
       <rdf:Seq>
          <rdf:li>http://twitter.com/TJalexander/statuses/1456808203</rdf:li>
          <rdf:li>http://twitter.com/xElsiex/statuses/1456808201</rdf:li>
          <rdf:li>http://twitter.com/mmama1215/statuses/1456808197</rdf:li>
          <rdf:li>http://twitter.com/kennethmaxey/statuses/1456808196</rdf:li>
          <rdf:li>http://twitter.com/katiestars/statuses/1456808195</rdf:li>
          <rdf:li>http://twitter.com/Zweeal/statuses/1456808194</rdf:li>
          <rdf:li>http://twitter.com/lilvicofficial/statuses/1456808193</rdf:li>
          <rdf:li>http://twitter.com/PrettyNitti/statuses/1456808192</rdf:li>
          <rdf:li>http://twitter.com/mrrobbo/statuses/1456808190</rdf:li>
          <rdf:li>http://twitter.com/smd75jr/statuses/1456808189</rdf:li>
          <rdf:li>http://twitter.com/BirdDiva/statuses/1456808188</rdf:li>
          <rdf:li>http://twitter.com/nouwen/statuses/1456808185</rdf:li>
          <rdf:li>http://twitter.com/gustavopereira/statuses/1456808184</rdf:li>
          <rdf:li>http://twitter.com/sky_7/statuses/1456808183</rdf:li>
          <rdf:li>http://twitter.com/fauzty/statuses/1456808182</rdf:li>
          <rdf:li>http://twitter.com/Cheriefaery/statuses/1456808181</rdf:li>
          <rdf:li>http://twitter.com/CarolineAttia/statuses/1456808180</rdf:li>
          <rdf:li>http://twitter.com/ukyo_rst/statuses/1456808179</rdf:li>
          <rdf:li>http://twitter.com/Len0r/statuses/1456808177</rdf:li>
          <rdf:li>http://twitter.com/jhill444faceboo/statuses/1456808175</rdf:li>
       </rdf:Seq>
     </items>
  </channel>
  <item rdf:about="http://twitter.com/TJalexander/statuses/1456808203">
     <dc:format>text/html</dc:format>
     <dc:date>2009-04-05T13:11:01+00:00</dc:date>
     <dc:source>http://www.twitter.com</dc:source>
     <dc:creator>t.j. alexander</dc:creator>
     <dc:date>2009-04-05T13:11:01+00:00</dc:date>
     <title>TJalexander: Photo: somethingtobelievein: i don</title>
     <link>http://twitter.com/TJalexander/statuses/1456808203</link>
     <description>TJalexander: Photo: somethingtobelievein: i don</description>
  </item>
  <item rdf:about="http://twitter.com/xElsiex/statuses/1456808201">
     <dc:format>text/html</dc:format>
     <dc:date>2009-04-05T13:11:01+00:00</dc:date>
     <dc:source>http://www.twitter.com</dc:source>
     <dc:creator>Elsie Constantinides</dc:creator>
     <dc:date>2009-04-05T13:11:01+00:00</dc:date>
     <title>xElsiex: my hairs gone all fluffy like :O !! nooooooooooooo !!!</title>
     <link>http://twitter.com/xElsiex/statuses/1456808201</link>
     <description>xElsiex: my hairs gone all</description>
  </item>
...

注意,清單 1 中的文檔看起來與原來的 Really Simple Syndication 格式驚人地相似。這不是一個巧合,因為 RDF Site Syndication 規范背後的理念是創建一種與 RDF 兼容的聚合格式。

大多數元素是可以顧名思義的。RDF Site Syndication 和 Really Simple Syndication 之間的一個主要區別是 <items> 元素,它是 <channel> 元素的一個子元素。這個元素提供 RDF 文件中包含的所有文檔鏈接的列表。該元素可以視為一個摘要的摘要。

考慮到上述因素,似乎應該創建兩個 JavaBeans:一個主要 “節” 和一個 JavaBeans。清單 2 顯示了 Channel 類。

清單 2. Channel 類

public class Channel {

 private String about;
 private String title;
 private String description;
 private String link;
 private String date;
 private List<String> items = new ArrayList<String>();

 public String getAbout() {
 return about;
 }
 public void setAbout(String about) {
 this.about = about;
 }
 public String getTitle() {
 return title;
 }
 public void setTitle(String title) {
 this.title = title;
 }
 public String getDescription() {
 return description;
 }
 public void setDescription(String description) {
 this.description = description;
 }
 public String getLink() {
 return link;
 }
 public void setLink(String link) {
 this.link = link;
 }
 public String getDate() {
 return date;
 }
 public void setDate(String date) {
 this.date = date;
 }
 public List<String> getItems() {
 return items;
 }
 public void setItems(List<String> items) {
 this.items = items;
 }
}

如上所示,Channel 類無非是一個直觀的 JavaBean,它描述包含在 <channel> 節中的信息。該類中的每一個屬性和 <channel> 的每一個子元素之間都有一種直接聯系。甚至有一個針對這些鏈接的 String 對象清單(List),這些鏈接是 <items> 元素的子元素。

清單 3 是另一個簡單的 JavaBeans 類,這個類代表提要中的一個文檔。

清單 3. Item 類

public class Item {

 private String format;
 private String date;
 private String link;
 private String creator;
 private String title;
 private String description;
 private String source;

 public String getSource() {
 return source;
 }
 public void setSource(String source) {
 this.source = source;
 }
 public String getFormat() {
 return format;
 }
 public void setFormat(String format) {
 this.format = format;
 }
 public String getDate() {
 return date;
 }
 public void setDate(String date) {
 this.date = date;
 }
 public String getLink() {
 return link;
 }
 public void setLink(String link) {
 this.link = link;
 }
 public String getCreator() {
 return creator;
 }
 public void setCreator(String creator) {
 this.creator = creator;
 }
 public String getTitle() {
 return title;
 }
 public void setTitle(String title) {
 this.title = title;
 }
 public String getDescription() {
 return description;
 }
 public void setDescription(String description) {
 this.description = description;
 }
}

如上所示,這個類包含一個項目的相關信息:title、creator(或 author)、description(摘要)和鏈接。

進一步深入代碼之前,首先需要檢查一個 Atom 示例文檔。請看 清單 4。

清單 4. 一個 Atom 示例文檔(Twitter public timeline)

<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
 <title>Twitter public timeline</title>
 <id>tag:twitter.com,2007:Status</id>
 <link type="text/html" rel="alternate" href="http://twitter.com/public_timeline"/>
 <updated>2009-04-06T12:20:02+00:00</updated>
 <subtitle>Twitter updates from everyone!</subtitle>
  <entry>
   <title>UMaineExtension: Backyard Poultry course</title>
   <content type="html">UMaineExtension: Backyard Poultry course</content>
   <id>tag:twitter.com,2007:http://twitter.com/UMaineExtension/statuses/1462447470</id>
   <published>2009-04-06T12:20:00+00:00</published>
   <updated>2009-04-06T12:20:00+00:00</updated>
   <link type="text/html" rel="alternate" href="http://twitter.com//1462447470"/>
   <link type="image/jpeg" rel="image" href="http://UM-crest_normal.jpg"/>
   <author>
    <name>UMaine Extension</name>
    <uri>http://www.extension.umaine.edu</uri>
   </author>
  </entry>
  <entry>
   <title>tmj_mem_adv: Ecommerce Marketing Manager http://tinyurl.com/cthahs</title>
   <content type="html">tmj_mem_adv: Ecommerce Marketing Manager</content>
   <id>tag:twitter.com,2007:http://twitter.com/1462447468</id>
   <published>2009-04-06T12:19:59+00:00</published>
   <updated>2009-04-06T12:19:59+00:00</updated>
   <link type="text/html" rel="alternate"
     href="http://twitter.com/statuses/1462447468"/>
   <link type="image/png" rel="image" href="http://83603474/twitter_normal.png"/>
   <author>
    <name>TMJ-MEM Advert Jobs</name>
    <uri>http://www.tweetmyjobs.com</uri>
   </author>
  </entry>
...

注意,<title> 元素是 <feed> 的直接子元素。而另一個元素是 <entry> 的直接子元素。今後您需要在代碼中處理這個問題。

現在模型已經完成,是時候進行實際編碼,以解析 Atom 提要並創建 RDF 文件了。AtomToRdf 類用於完成這個任務。清單 5 顯示了這個類本質。

清單 5. AtomToRdf 的本質

public class AtomToRdf {

 . . .
 private Channel channel = new Channel();
 private List<Item> itemList = new ArrayList<Item>();

 public static void main(String[] args) {
 AtomToRdf atomToRdf = new AtomToRdf();
 atomToRdf.go();
 }

 private void go() {
 parseAtom();
 createRdf();
 }
 . . .
}

如果一切都這樣簡單就好了!實際情況是 main() 方法只是在一個實例化的 AtomToRdf 類上執行了一個私有方法 go()。這是一種跳出靜態上下文的方法。go() 方法反過來執行兩個相當顧名思義的方法:parseAtom() 和 createRdf()。第一個方法是閱讀器,第二個方法是寫入器。

為確保從 Atom 提要中讀取的信息能夠用於 AtomToRdf 對象中的所有方法,必須聲明兩個局部可用的對象變量,如 清單 5 所示。一個是 Channel 類的一個實例(稱為 channel)。另一個是包含一個或多個 Item 對象的 List 對象(稱為 itemList)。

清單 6 顯示了 parseAtom() 方法的開始部分。該方法使用 StAX 來解析 Atom 提要。這段代碼首先實例化一個新的 XMLInputFactory 對象,然後打開一個包含 Atom 格式的 Twitter public timeline 的 InputStream 對象。這個 StAX InputFactory 從 InputStream 創建一個 XMLEventReader 對象。在 “拖動—解析” Atom 提要的過程中,StAX 用這個對象來識別 事件。事件的一些例子比如文檔啟動、元素啟動和元素結束。

清單 6. 開始解析 Atom

 private void parseAtom() {
    try {
      XMLInputFactory inputFactory = XMLInputFactory.newInstance();
      InputStream in = new URL("http://twitter.com/statuses/public_timeline.atom") 
  .openStream();

      XMLEventReader eventReader = inputFactory.createXMLEventReader(in);

      boolean inEntry = false;
      Item currentItem = null;

      while (eventReader.hasNext()) {
...

要處理這兩個 <title> 元素,這個 isEntry Boolean 用於區分它們。如果 Boolean 為 True,解析器檢查 <title> 元素,該元素是 <entry> 的一個子元素。

變量 currentItem 用於存儲輸出文件中的每個 <item> 節中將包含的信息。每次解析器遇到輸入文件中的另一個 <entry> 元素時,一個新的 currentItem 對象將被實例化。每次解析器遇到 <entry> 元素的結尾時,現有的 currentItem 對象添加到 Item 對象列表(itemList)。

最後,清單 6 開始解析器循環。本質上,那條 while 語句的意思是 “只要解析器遇到 任何事件,它將重復執行大括號({})裡面的代碼。”

急需解決的問題是:將遇到哪種事件?如何處理這些事件?請看 清單 7。

清單 7. 解析 Title 元素

if (event.isStartElement()) {
  StartElement startElement = event.asStartElement();

  if (event.asStartElement().getName().getLocalPart().equals("title")) {
     event = eventReader.nextEvent();
     String title = event.asCharacters().getData();

     if (!inEntry) {
     channel.setTitle(title);
     } else {
     currentItem.setTitle(title);
     }

     continue;
  }
...

當這段代碼遇到一個事件時,它首先檢查這個事件是不是一個新元素的開端。如果是,則一個 StartElement 對象被實例化。然後檢查這個元素的名字。如果這個元素的名字是 title,這段代碼將把該元素的實際內容放到字符串變量 title 中。

還記得 isEntry 變量嗎?這個變量將在這裡使用,因為 — 您可能還記得 — 命名為 title 的元素出現在 Atom 提要的兩個位置。如果 isEntry 設置為 True,代碼知道檢查一個文檔的標題,而不是整個提要的標題。對於前一種情況,將設置 currentItem 對象的 title 屬性;對於後一種情況,將設置 channel 對象的 title 屬性。

最後,continue 語句是一條標准的 Java 語句,它的意思是 “只要到此就繼續循環”。換句話說,當代碼處理完這個事件後,將開始尋找更多事件。

如果您查看整個代碼,您將發現有許多代碼塊與 清單 7 中的代碼類似。區別在於每個代碼塊檢查 Atom 提要中的一個不同元素,然後在正確的對象上設置適當的實例變量。

循環結束時,代碼將擁有一個完全填充的 Channel 對象和一個完全填充的 Item 對象列表。這些對象將被讀取,其中的信息將用於創建 RDF 文件。

在檢查代碼以創建 RDF 文檔之前,首先必須理解已在 AtomToRdf 中定義的一些常量(見 清單 8)。

清單 8. 在 AtomToRdf 中定義的常量

private static final String DUBLIN_CORE_PREFIX = "dc";
private static final String DUBLIN_CORE_URI = "http://purl.org/dc/elements/1.1/";
private static final String RDF_PREFIX = "rdf";
private static final String RDF_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
private static final String RSS_URI  = "http://purl.org/rss/1.0/"; 

為何需要這些常量呢?讓我們回頭看看 清單 1 中的 RDF 示例文檔。您將看到 RDF 輸出需要名稱空間,在很多情況下,這些名稱空間是重復的。這些常量能夠使您更輕松地引用那些名稱空間和它們對應的 URI。清單 9 中的代碼開始輸出。

清單 9. 開始輸出

  private void createRdf() {
  try {

 XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
   XMLStreamWriter xmlw = xmlof.createXMLStreamWriter
  (new FileOutputStream ("c:/twitter.rdf"));
   xmlw.writeStartElement(RDF_PREFIX, "RDF", RDF_URI);
   xmlw.writeNamespace(RDF_PREFIX, RDF_URI);
   xmlw.writeNamespace("",RSS_URI);
   xmlw.writeNamespace(DUBLIN_CORE_PREFIX, DUBLIN_CORE_URI);
   xmlw.writeCharacters("\n");
   xmlw.writeCharacters("  ");

   writeChannel(xmlw);
   writeItems(xmlw);

   xmlw.writeCharacters("\n");
   xmlw.writeEndElement();
   xmlw.writeEndDocument();
   xmlw.close();
   } catch (Exception e) {
   e.printStackTrace();
   }
  }

再次使用了 StAX API。區別在於這一次它用於生成輸出而不是讀取輸入。這段代碼首先實例化一個新的 XMLOutputFactory 對象,然後從一個 FileOutputStream 對象創建一個 XMLStreamWriter,該對象指向 c:/twitter.rdf(輸出文件的名稱和位置)。您可能需要根據自己的環境更改文件位置。

這段代碼開始寫出這些元素。它首先從根元素開始,並對根元素使用前綴 rdf 和它對應的 URI。下面三行定義與根元素關聯的各種名稱空間和相應的前綴。注意,RSS_URI 常量代表默認前綴,因此一個空字符串用作前綴。

接下來兩行的目的是格式化,使輸出更適合人類閱讀。您將在整個輸出代碼中看到大量這種情況。

下面兩行調用單獨的方法,它們用作輸出例程的 “重要部分”。第一種方法寫出 <channel> 節,第二種方法寫出每個 <item> 節。

下面幾行關閉根元素和文檔本身。最後,XMLStreamWriter 對象關閉。

您可能注意到 清單 10 中的一種模式。首先,創建一個帶有恰當 about 屬性的父元素(通常命名為 channel)。注意,about 屬性需要 rdf 名稱空間。about 屬性的值只是一個 URL,它指向 RDF Site Syndication 中包含的信息。為此,我使用了 Twitter 的 URL。

清單 10. writeChannel() 方法

  private void writeChannel(XMLStreamWriter xmlw) throws Exception {
 xmlw.writeStartElement("channel");
 xmlw.writeAttribute(RDF_PREFIX, RDF_URI, "about",
  "http://www.twitter.com");
 xmlw.writeCharacters("\n");
 xmlw.writeCharacters("     ");
 xmlw.writeStartElement("title");
 xmlw.writeCharacters(channel.getTitle());
 xmlw.writeEndElement();
 xmlw.writeCharacters("\n");
 xmlw.writeCharacters("     ");
 xmlw.writeStartElement("description");
 xmlw.writeCharacters(channel.getDescription());
 xmlw.writeEndElement();
 xmlw.writeCharacters("\n");
 xmlw.writeCharacters("     ");
...

這是您第二次在輸出中看到 about 屬性。了解它為什麼在那裡很重要,其原因是 about 屬性定義 “主語-謂語-賓語” 三元組中的主語。在這個例子中主語是一個 URL(這種情況很普遍)。每個子元素(比如 <title>)代表一個謂語。每個元素的內容是賓語。

在兩個格式化行之後,創建 <title> 元素並使用從 Atom 提要收集的標題填充,然後創建 <description> 元素等。

即使 清單 10 中只提供了兩個元素,您可能還是注意到了一種模式出現。首先創建一個元素,然後使用來自 Channel 對象的內容填充這個元素,然後元素結束。這個過程將對包含在 Channel 對象中的所有數據重復。

為了使事情更直觀,Channel 對象中的屬性名稱與 <channel> 節中的元素名稱相同,這使在代碼和輸出之間進行正確映射更加容易。

在 清單 11 中,writeItems() 方法有一些不同,因為它不是寫一個節,而是很多節。它對 Atom 提要中的每個 <entry> 元素寫一個節。指向該方法開始處的 for 循環確保這一點得以實現。

清單 11. writeItems() 方法

  private void writeItems(XMLStreamWriter xmlw) throws Exception {
   xmlw.writeCharacters("\n");
   xmlw.writeCharacters("  ");

 for (Item item : itemList) {
 xmlw.writeStartElement("item");
 xmlw.writeAttribute(RDF_PREFIX, RDF_URI,
  "about", item.getLink());
 xmlw.writeCharacters("\n");
 xmlw.writeCharacters("     ");

 xmlw.writeStartElement(DUBLIN_CORE_PREFIX,"format",
  DUBLIN_CORE_URI);
 xmlw.writeCharacters(item.getFormat());
 xmlw.writeEndElement();
 xmlw.writeCharacters("\n");
 xmlw.writeCharacters("     ");
...

對於 itemList 中的每個 Item 對象,將創建一個新的 <item> 元素。同樣,一個特定於名稱空間的 about 屬性指向該文檔的鏈接。在這個例子中,這個鏈接指向 Twitter 上的一個特定用戶的一篇文章。

經過一些格式化之後,創建了一個稱為 format 的子元素。這個 format 元素描述文檔中的輸出格式。在這裡,這個元素是 text/html 格式。注意,這裡使用了 Dublin Core 元數據而不是 RDF Site Syndication 標准或 RDF 標准指定的元數據。那是因為這兩種標准都不支持定義文檔格式。

在以上代碼塊中,出現了一種模式。對於 Item 類中的每個屬性,一個新元素被創建並關聯到一個與該屬性名對應的元素。

總之,這就是那段代碼,現在讓我們來看看它實際上是否像所說的那樣有效。

測試代碼

將包含本文的這個壓縮文件 — AtomToRdf.zip — 解壓到您選擇的一個測試目錄。您將看到已經大致介紹過的三個文件:Item.java、Channel.java 和 AtomToRdf.java。

使用您最鐘愛的集成開發環境(IDE)或進入一個命令提示,然後使用與 1.6 版兼容的 Java 編譯器編譯那些類。然後不帶命令行參數執行 AtomToRdf.class。

如果您沒有更改提供的代碼的內容,您的 C 盤根目錄下將創建一個文件:twitter.rdf。該文件的格式將與 清單 1 中的格式相同。

如何知道這是不是一個有效的 RDF 文件呢?只需用一個驗證器檢驗一下。幸運的是,W3C 上的一些好伙伴為您創建了一個校驗器,它位於:http://www.w3.org/RDF/Validator。訪問這個 URL,然後將 twitter.rdf 的內容粘貼到文本區域。單擊 Parse RDF。您將看到一個窗口,窗口頂部顯示 “Your RDF document validated successfully.”。恭喜您,您成功了!

結束語

隨著 Semantic Web 成為技術革命的前沿技術,站點發布與 Semantic Web 標准兼容的文檔變得很重要。RDF 就是這些標准之一。

使用 RDF Site Syndication,網絡管理員能夠生成與 Atom 提要類似的、兼容 RDF 的文檔。這將提供聚合和語義雙重好處。

使用 Java 編程語言和 StAX API,可以輕松解析一個 Atom 提要並將其轉換為一個 RDF 文檔,然後可以用這個 RDF 文檔來提供特定於語義的提要。

本文隨文源碼下載

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved