DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 用 XPath 在 PHP Web 站點中顯示 Google Calendar 事件
用 XPath 在 PHP Web 站點中顯示 Google Calendar 事件
編輯:XML詳解     

本文示例源代碼或素材下載

  Google Calendar 和其他在線日歷應用程序將提供簡單的集中式系統,在這類系統中,在線社區可以維護事件日歷,而社區成員可以獲得關於最新事件的信息。但是許多組織更傾向於在其社區門戶、論壇或博客中顯示事件日歷。他們經常把事件日歷信息從在線日歷應用程序復制到 Web 站點中,降低了在線集中管理事件的效率。Google Calendar 提供了集成應用程序接口 (API),從而為這個問題提供了很好的解決方案。了解如何使用 XPath 提取並在 PHP Web 站點中顯示 Google Calendar 數據。

  當幾年前我是一名自由 Web 開發人員時,我為一個特殊車型汽車的擁有者和愛好者社區(通常稱為汽車俱樂部,它們在我生活的地方非常流行)開發了一個用 PHP 編寫的 Web 門戶。在聯系我的幾年以前,一些汽車俱樂部管理者就已經學習了基本的 Web 技巧並且自己創建了一個 Web 站點。隨著站點的成長,站點積聚了大量頁面,其中一些發布了單獨的事件日歷信息的頁面已經失效。由於站點的主要目的是向公眾及社區成員通知活動,因此這些頁面中插入了事件日歷信息。

  隨著時間的推移,這些社區事件日歷的不同快照不同步了。雖然很多事件已經過去很久了,但頁面中仍然保留有與之相關的側欄。即使有正確的管理和有效的 Web 設計,維護各個網頁中事件日歷數據的各個副本也是一項花費大量時間和容易出錯的任務。他們發現不是汽車俱樂部 Web 站點在為他們工作,而是自己在為那個 Web 站點工作。他們聯系到我,希望我能給他們展示一種更好的方法。

  他們希望站點中有論壇,俱樂部成員可以在其中討論他們喜愛的汽車,還要有一個集中的新聞頁面,用於發布最新的事件報導和通告。在這個新聞頁面中,他們可以向不斷增多的成員通知事件,例如聯歡會、自駕車到野外和鄉村游玩以及討論成員交費和預算事項的全體成員會議。更重要的是,他們希望不必維護位於各個位置的多個事件日歷副本。希望在一個位置輸入事件日歷並且能夠在站點中的任意位置訪問該信息。

  Google Calendar 和 Google 數據 API

  在線日歷應用程序(如 Google Calendar)提供了一種解決方案。通過集中顯示和管理事件,Google Calendar 用戶可以在一個站點中共享和維護事件日歷,消除了事件組織過程中可能造成錯誤的其中一個源頭。社區成員可以訪問在線日歷來獲悉最新事件和活動,而不會由於各個 Web 頁面中過時的事件信息而導致混亂。看上去在線日歷應用程序是十分理想的解決方案。

  在用 Drupal 內容管理系統(請參閱 參考資料)開發俱樂部的 Web 站點時,我建議俱樂部的管理者使用 Google Calendar 來維護事件日歷。最初,這個建議得到了認同,並且他們反饋說效率很高,因為可以輕松地使用 Drupal 管理前端來更新我為他們創建的事件側欄。但是隨著時間的推移,俱樂部的成功意味著有更多事件需要通告,而編輯事件側欄也從輕松有趣變得愈加繁瑣。

  Google 數據 API 及其對 Google Calendar 事件數據的訪問權提供了一種擺脫這種困境的方法。Google 數據 API 提供了一個 Atom 發布協議(Atom Publishing Protocol,APP)的實現,這是用於讀取和更新各種類型的文檔和信息的 Web 服務 API。還有適用於 Microsoft® .Net、Java™ 編程語言、Python 和 PHP 的第三方集成 API,這些集成 API 在一組面向對象的封裝類中封裝了大部分 Google 數據 API 功能。

  經過一些研究之後,我能夠把汽車俱樂部的 Drupal 站點擴展為擁有一直保持最新信息的事件側欄,該側欄將從 Google Calendar 帳戶中提取最新的事件日歷數據。

  Google Calendar 摘要

  Google 數據 API 將提供大量包含由 Google 提供的許多 Web 服務的文檔和信息的 Atom 摘要。Google Calendar 也不例外,提供了一些封裝了主要 Google Calendar 數據的摘要。有經過 HTTP 驗證的公共摘要。要檢索並與經過驗證的摘要進行交互,HTTP 客戶需要提供驗證信息以及 HTTP GET 請求。經過驗證的摘要還能夠用 HTTP POST 請求來更新 Google Calendar 帳戶。使用經過驗證的摘要的 HTTP 客戶可以添加和刪除事件,訂閱和取消訂閱日歷,以及創建日歷和從 Google 帳戶中刪除日歷。

  Google Calendar API 提供了用戶可以從 Google Calendar GUI 訪問的所有單獨日歷的摘要。這包含用戶所擁有的日歷、其他人所擁有但是用戶已經訂閱的日歷,以及用戶已經以只讀狀態導入的日歷。這些日歷都有各自經過驗證的私有和公共事件摘要,其中列出了日歷中的各個事件。本文介紹的重點是公共事件摘要。

  使 Google Calendar 摘要成為公共摘要

  一個賬戶可以有許多 Google Calendar 日歷的公共事件摘要,獲得摘要的方法是登錄到 Google Calendar 應用程序中,選擇有興趣處理的日歷,並單擊日歷名稱的向下小箭頭。單擊此箭頭後,摘要名稱旁邊將顯示一個菜單。選擇 Calendar Settings,圖 1 中被圈選的部分。

  圖 1. 所選日歷的 Google Calendar 下拉菜單

用 XPath 在 PHP Web 站點中顯示 Google Calendar 事件

  然後 Google Calendar 應用程序將轉到可以選擇各個日歷設置(例如事件的時區和日歷名稱)的頁面。公共摘要的一個重要選項是日歷本身是公共的還是共享的 日歷。要使日歷共享並且可以通過公共事件摘要來檢索,請單擊 Change sharing settings 選項,如圖 2 所示:

  圖 2. 將日歷的可視性更改為共享或公共

用 XPath 在 PHP Web 站點中顯示 Google Calendar 事件

  頁面將轉到可以選擇 Share all information on this calendar with everyone 的 Share this calendar 選項卡。系統將顯示一系列彈出式問題,詢問您是否確實要使日歷公開。回答 Yes,並且不要忘記單擊選項卡底部的 Save 來保存設置。單擊 Back to Calendar 繼續向日歷中添加事件。

  檢驗 Google Calendar 摘要

  要獲得 Google Calendar 摘要的示例,請參考 下載 部分中提供的代碼樣例中的 full.XML 文件。我還提供了本文中使用的代碼示例的虛構摘要鏈接(請參閱 參考資料)。

  事件摘要包含描述事件的各個元素,例如事件標題、描述以及事件發生的時間和地點。Google Calendar 還管理了一張受邀參加事件的人員列表,只要事件有更新就通過這些人員的電子郵件列表發送事件詳細信息。如果這些電子郵件地址表示 Google Calendar 用戶,那麼他們可以通過應用程序響應邀請,並且事件還將保存他們的出席狀態。集成出席詳細信息不在本文討論的范圍內,出席詳細信息描述的是基本事件信息,例如事件標題和事件發生的時間和地點。清單 1 是樣例摘要中的一個事件條目。

  清單 1. 樣例 Google Calendar 事件摘要條目:ID 和時間戳

  <entry>
    <id>
      http://www.google.com/calendar/feeds/foss.sanjuan%40gmail.com/public/full/
      s19o15ve3nn209gv5qf6c43ao4
    </id>
    <published>2007-08-12T15:45:40.000Z</published>
    <updated>2007-08-12T15:53:37.000Z</updated>
    ...
    ...

  id 元素將提供用於在 Google Calendar 系統內識別此事件的惟一統一資源標識符(Uniform Resource IdentifIEr,URI)。它不但包含惟一編號,而且還標識了檢索到它時所在的摘要。published 和 updated 元素將使用 RFC 3339 時間戳格式。updated 元素用於指示最後一次編輯事件的時間,如果是新事件,則是事件的創建時間。

  在增加了 id、published 和 updated 元素後,元素中就有了更多可讀信息,如清單 2 所示。此信息可以顯示在側欄或事件頁面中。

  清單 2. 樣例 Google Calendar 事件摘要條目:標題、作者和狀態

    ...
    ...
    <title type="text">Linux Install Fest</title>
    ...
    ...
    <author>
      <name>Open Source San Juan</name>
      <email>[email protected]</email>
    </author>
    ...
    ...
    <gd:eventStatus value="http://schemas.google.com/g/2005#event.confirmed"/>
    ...
    ...

  title 元素是一個標識事件的簡單字符串。它不必惟一。author 元素包含 name 和 email 元素。事件的作者是把事件輸入到日歷中的 Google Calendar 用戶。在相應地設置了經過驗證的摘要和寫訪問權限後,除了日歷的擁有者之外 Google Calendar 用戶也可以在其他用戶的日歷中創建事件。表 1 描述了 status 元素的可能值。

  表 1. gd:eventStatus 元素的可能值

值 描述 http://schemas.google.com/g/2005#event.cancelled 事件被取消。 http://schemas.google.com/g/2005#event.confirmed 事件被確認。 http://schemas.google.com/g/2005#event.tentative 事件已暫時排定。

  接下來是描述事件發生的時間和地點的元素,如清單 3 所示:

  清單 3. 樣例 Google Calendar 事件摘要條目:時間和地點

    ...
    ...
    <gd:when startTime="2007-08-03T16:00:00.000-04:00"
      endTime="2007-08-03T19:00:00.000-04:00"/>
    <gd:where
      valueString="Guaynabo Public High School Auditorium, Guaynabo, PR"/>
  </entry>

  when 元素包含兩個屬性:事件的開始時間和結束時間,兩者都使用 RFC 3339 時間戳格式。where 元素的 valueString 屬性是可以從 Google Calendar 應用程序和通過 API 來完全檢索的。Google Calendar 和 Google 數據 API 不支持按個別元素搜索。相反,他們將對 string 元素(例如 title、author 和 description,以及 where 元素的 valueString 屬性)進行全文搜索。正如您稍後將看到的,例外情況是 Google 數據 API 支持設置開始日期范圍以限制查詢結果中包括的事件。

  限制 Google Calendar 摘要的內容

  為了支持檢索精確數據集,Google 數據 API 在 HTTP GET 請求中支持查詢參數的概念。使用這些參數,Google 數據 API 客戶可以指定要返回的最大條目數(使用 max-results 參數),使用哪些元素對摘要條目進行排序(通過 orderby 參數),以及要返回的條目范圍包含的開始時間和結束時間(通過 start-min 和 start-max 參數)。最後這兩個參數指示要包含在事件結果集中的事件開始時間的日期范圍。start-min 是指范圍的開始日期,start-max 是指范圍的結束日期。兩個參數都是用 RFC 3339 時間戳格式表示的。

  最後,可以通過在查詢字符串中包含 singleevents 參數使重復出現的事件更易於解析。當 singleevents 參數的值為 true 時,系統將把重復出現的事件視為明顯的單個事件在摘要中指定。否則,重復出現的事件將包括 <gd:recurrence> 元素,該元素包含 iCal 格式的重復出現規則。iCal 格式以及如何解析該格式不在本文討論的范圍內。

  清單 4 是添加了所有查詢參數後事件摘要 URL 的顯示內容。編寫時為了具有可讀性,把一個長的 URL 斷開成了若干行。

  請單 4. 帶有查詢參數的樣例 Google Calendar 摘要 URL

  http://www.google.com/calendar/feeds/foss.sanjuan%40gmail.com/public/full?
  max-results=25&
  singleevents=true&
  orderby=starttime&
  start-min=2007-05-22T09%3A58%3A47-04%3A00&
  start-max=2007-11-06T09%3A58%3A47-04%3A00

  用 PHP 解析 Google Calendar 摘要

  既然已經討論了 Google Calendar 事件摘要的元素和如何查詢摘要以獲得感興趣的條目,接下來將探討解析摘要和在頁面中顯示摘要的方法。PHP 提供了若干個可用於檢索事件條目列表和提取每個事件的標題、日期、時間和位置的 XML API。首先將從文檔對象模型(Document Object Model,DOM)API 開始。

  用 DOM 解析摘要

  XML DOM API 是一個標准的 XML 解析 API,而且它最常用於編寫 XML 應用程序。DOM API 的用法不在本文討論的范圍內,但是我將詳細介紹解析 Google Calendar 事件摘要的示例程序,並說明 DOM API 的一些優點和缺點。

  XML DOM API 的優點之一是速度很快。它將把整個 XML 文檔裝載到內存中,並且從 XML 文檔中檢索元素全都在內存中進行。不過這樣做對於大型的 XML 文件來說效率很低,它只適用於 2 MB 或 3 MB 的 XML 文件。

  XML DOM API 的另一個優點是可讀性。用 DOM 解析 XML 包含用於打開 XML 文檔和從層次結構樣式的文檔中檢索特定元素的命令。它幾乎就象英語一樣,告訴 PHP 去 “獲得帶有 ‘entry’ 標記名稱的元素”。清單 5 演示了這些內容。

  清單 5. 用 DOM API 解析 Google Calendar 事件摘要

<?PHP
  $confirmed = 'http://schemas.google.com/g/2005#event.confirmed';
  $three_months_in_seconds = 60 * 60 * 24 * 28 * 3;
  $three_months_ago = date("Y-m-dTh:i:sP", time() - $three_months_in_seconds);
  $three_months_from_today = date("Y-m-dTh:i:sP", time() + $three_months_in_seconds);
  $feed = "http://www.google.com/calendar/feeds/foss.sanjuan%40gmail.com/" .
    "public/full?orderby=starttime&singleevents=true&" .
    "start-min=" . $three_months_ago . "&" .
    "start-max=" . $three_months_from_today;
  $doc = new DOMDocument();
  $doc->load( $feed );
  $entrIEs = $doc->getElementsByTagName( "entry" );
  foreach ( $entrIEs as $entry ) {
    $status = $entry->getElementsByTagName( "eventStatus" );
    $eventStatus = $status->item(0)->getAttributeNode("value")->value;
    if ($eventStatus == $confirmed) {
      $titles = $entry->getElementsByTagName( "title" );
      $title = $titles->item(0)->nodeValue;
      $times = $entry->getElementsByTagName( "when" );
      $startTime = $times->item(0)->getAttributeNode("startTime")->value;
      $when = date( "l JS of F Y - h:i A", strtotime( $startTime ) );
      $places = $entry->getElementsByTagName( "where" );
      $where = $places->item(0)->getAttributeNode("valueString")->value;
      print $title . "
";
      print $when . " AST
";
      print $where . "
";
      print "
";
    }
  }
?>

  在這段代碼樣例中,將用所需的參數設置摘要 URL,打開摘要,然後獲得 DOMNodeList 中的所有事件條目,可以用 foreach 迭代程序來處理。對於每個事件條目,將比較 gd:eventStatus 元素的值屬性與確認事件的已知值。注意,無需為 element 標記指定 gd: 前綴。PHP DOM API 知道名稱空間,並且需要刪除 gd: 前綴,否則解析器將找不到想要的元素。

  如果確認了事件條目,則將檢索 title、gd:when 和 gd:where 元素。gd:when 和 gd:where 元素要求請求具體屬性,例如 startTime 和 valueString。需要以方便閱讀的方法顯示事件日期並且解析 gd:when 元素的 startTime 屬性將其轉換為表示時間的長整數。然後將此信息傳遞給帶有常用顯示格式的日期函數。

  DOM API 的一個缺點是有些冗長。雖然每條語句的目的十分明確,因為它匹配算法的文本描述,但是它不像代碼包一樣扼要。DOMNode 和 DOMDocument 類的 getElementsByTagName 和 getAttributeNode 方法將添加相當多的代碼。

  用 SAX 解析摘要

  另一個可用於 PHP 的 XML 解析 API 是 Simple API for XML (SAX) API。DOM API 具有可讀性但冗長,而 SAX 可以很簡要但難於遵循,即使是對於有經驗的開發人員。SAX 與 DOM 之間的差別在於 SAX 不把整個 XML 文檔裝載到內存中,而 DOM 卻這樣做。高效的 SAX 處理代碼可以快得多,而內存使用量可以保持在最低並且可以根據應用程序的具體需求來調整。使用 DOM,內存使用量要求從應用程序處理的最大 XML 文檔大小開始向上攀升。

  清單 6 是 SAX 處理 Google Calendar 事件摘要的示例片段。要獲得完整示例,請參考 下載 部分中提供的示例腳本包中的 sax_sample.PHP 腳本。

  清單 6. 用 SAX API 解析 Google Calendar 事件摘要

  function startElement( $parser, $tagName, $attr )
  {
    global $g_entrIEs, $g_tagName, $g_confirmed, $g_is_confirmed,
      $g_in_entry, $g_in_originalevent;
    if ( $tagName == 'ENTRY' ) {
      if ($g_is_confirmed || count( $g_entrIEs ) == 0) {
        $g_entrIEs []= array();
      }
      $g_is_confirmed = false;
      $g_in_entry = true;
    }
    else if ($tagName == 'GD:EVENTSTATUS')
    {
      if ($attr['VALUE'] == $g_confirmed) {
        $g_is_confirmed = true;
      }
    }
    else if ($tagName == 'GD:WHEN' && $g_is_confirmed &&
      $g_in_originalevent == false)
    {
      $startTime = date( "l JS of F Y - h:i A", strtotime($attr['STARTTIME']) );
      $g_entries[ count( $g_entrIEs ) - 1 ]['when'] = $startTime;
    }
    else if ($tagName == 'GD:WHERE' && $g_is_confirmed)
    {
      $g_entries[ count( $g_entrIEs ) - 1 ]['where'] = $attr['VALUESTRING'];
    }
    else if ( $tagName == 'GD:ORIGINALEVENT' ) {
      $g_in_originalevent = true;
    }
    $g_tagName = $tagName;
  }
  function endElement( $parser, $tagName )
  {
    global $g_tagName, $g_in_entry, $g_in_originalevent;
    if ( $tagName == 'ENTRY' ) {
      $g_in_entry = false;
    }
    else if ( $tagName == 'GD:ORIGINALEVENT' ) {
      $g_in_originalevent = false;
    }
    $g_tagName = null;
  }
  function textData( $parser, $text )
  {
    global $g_entrIEs, $g_tagName, $g_in_entry;
    if ($g_tagName == 'TITLE' && $g_in_entry) {
      $g_entries[ count( $g_entrIEs ) - 1 ]['title'] = $text;
    }
  }

  這段代碼顯示了 startElement、endElement 和 textData 函數,這些函數都是使用 SAX 示例腳本中的 SAX 解析器引擎注冊的。這部分代碼顯示了如何處理感興趣的幾個元素。代碼變得十分復雜,因為 SAX 中的 XML 元素是按照從頂部到底部的順序從 XML 文檔中讀取的。在處理所需的一些元素之前不能檢查當前事件條目是否已確認。例如,gd:eventStatus 元素比 title 元素晚出現在事件中。復雜度的另一個根源是摘要有 title 元素,並且每個條目也有 title 元素。需要設置一個標志讓代碼知道讀取的是不是條目內的 title 元素。重復出現的事件的 gd:originalEvent 元素中還有一個 gd:when 元素,該元素不是您感興趣的 gd:when 元素。如果沒有這個狀態檢查邏輯,單純匹配元素名稱將生成錯誤輸出。

  通過這個示例,您可以看到 SAX API 的兩個缺點:它比 DOM API 冗長得多,而且經過與 DOM 樣例代碼的比較後,SAX 解析器更加復雜。

  用 Zend Google API 封裝程序解析摘要

  Zend TechnologIEs 與 Google 合作擴展了 Zend 框架,為 PHP 提供了一組面向對象類,用於隱藏 Google 數據 API 的 Atom 摘要的詳細信息,從而提供對所有 Google 數據信息的支持。這些面向對象類有很多優點,包括將各種 Google 數據 API 文檔呈現為具有方法和簡單參數的抽象對象,以及隱藏 Atom 摘要和 HTTP 協議操作(例如 GET、PUT 和 POST)的詳細信息。這些類還把用戶驗證的詳細信息封裝到 Google 數據 API 中,使它更易於寫入支持 Google 數據 API 所有功能(例如創建和更新來自第三方客戶的事件)的應用程序中。

  雖然這樣做為不熟悉 XML 解析和 HTTP 協議詳細信息的開發人員簡化了開發工作,但是 Zend 框架 Google 數據 API 類並非沒有缺點。如清單 7 所示,代碼十分冗長,因為許多對象構造函數都不帶參數。因此,必須在創建對象之後通過屬性設置選項。

  清單 7. 用 Zend PHP 類請求和處理 Google Calendar 事件摘要

<?PHP
require_once 'Zend/Loader.PHP';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Calendar');
$three_months_in_seconds = 60 * 60 * 24 * 28 * 3;
$three_months_ago = date("Y-m-dTh:i:sP", time() - $three_months_in_seconds);
$three_months_from_today = date("Y-m-dTh:i:sP", time() + $three_months_in_seconds);
// Create an instance of the Calendar service without authentication,
// for read-only Access to a public feed
$service = new Zend_Gdata_Calendar();
$query = $service->newEventQuery();
$query->setUser('foss.sanjuan%40gmail.com');
$query->setVisibility('public');
$query->setProjection('full');
$query->setOrderby('starttime');
$query->setStartMin($three_months_ago);
$query->setStartMax($three_months_from_today);
// RetrIEve the event list from the calendar server
try {
  $eventFeed = $service->getCalendarEventFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
  echo "Error: " . $e->getResponse();
}
// Iterate through the list of events, outputting them as an Html list
print "<ul>
";
foreach ($eventFeed as $event) {
  print "<li>" . $event->title . "</li>
";
  $startTime = $event->when->startTime;
  print "<li>" . date("l JS of F Y - h:i A", strtotime( $startTime ) );
  // Google Calendar API's support of timezones is buggy
  print " AST</li>
";
  print "<li>" . $event->where->valueString . "</li>
";
}
print "</ul>
";

  Zend Google 數據 API 類的優點之一是在檢索到 eventFeed 對象後,摘要的元素和屬性可以像 eventFeed 對象的屬性一樣按層次結構遍歷。我認為這樣做可以更輕松地閱讀處理代碼,因為各個元素都是按照類似於 XML 文檔中提供的樣式來組織的。不同於 DOMNode 的 getAttributeNode("attributeName")->value 方法,也可以按照層次結構的樣式從父元素遍歷屬性。

  用 XPath 和 SimpleXML 進行解析

  我認為由於支持使用 XPath 查詢 XML 文檔,因此 SimpleXML API 是最易於使用的 XML 解析 API 之一。它把 XML 文檔封裝成已裝載的 XML 文檔的分層對象屬性集。這類似於 DOM 返回可以按層次結構遍歷 DOMNode 對象實例的方法。類似於 DOM 的 DOMNode 對象但不同於 Zend 類,需要通過調用 attributes() 方法來檢索元素的屬性。這將把保存屬性的對象作為對象屬性返回。清單 8 提供了用 SimpleXML 解析和遍歷 Google 數據 API 日歷摘要所需的所有邏輯。

  清單 8. 用 XPath 和 SimpleXML 解析 Google Calendar 事件摘要

  $s = simpleXML_load_file($feed);
  foreach ($s->entry as $item) {
    $gd = $item->children('http://schemas.google.com/g/2005');
    if ($gd->eventStatus->attributes()->value == $confirmed) {
?>
      <font size=+1><b>
        <?PHP print $item->title; ?>
      </b></font><br>
<?PHP
      $startTime = '';
      if ( $gd->when ) {
        $startTime = $gd->when->attributes()->startTime;
      } elseif ( $gd->recurrence ) {
        $startTime = $gd->recurrence->when->attributes()->startTime;
      }
      print date("l JS of F Y - h:i A", strtotime( $startTime ) );
      // Google Calendar API's support of timezones is buggy
      print " AST<br>";
?>
      <?PHP print $gd->where->attributes()->valueString; ?>
      <br><br>
<?PHP
    }
  } ?>

  PHP 的 SimpleXML API 的一個缺點是它的解析速度比 DOM 或 SAX 慢,多達四倍。此缺點源於 SimpleXML 將通過使用 PHP 的動態特性動態創建元素和屬性節點。這一點與在類節點中定義元素和屬性節點的 Zend Google 數據 API 類形成對照。這使得用 Zend 類逐層遍歷節點的速度更快。

  SimpleXML 的另一個缺點是支持 XML 名稱空間。要從名稱空間中檢索元素,需要對元素調用 children() 方法。這樣做將返回以該名稱空間的元素為屬性的對象。DOM 和 Zend 類提供了更好的支持,即將所有名稱空間的元素表示為可按層次遍歷的節點或元素。

  性能注意事項和緩存

  討論 PHP 中的 XML 解析時,我注意到 SimpleXML 可能會比 DOM 或 SAX 解析慢很多倍。我選擇 SimpleXML 的原因是它比 SAX 更易於使用並且有助於獲得比 DOM 更具有可讀性的 XML 解析代碼。SimpleXML 動態生成元素和屬性節點作為其他節點的屬性,有利於獲得幾乎像 Zend Google 數據 API 類一樣可讀的節點遍歷代碼。

  但是,本文中提供的代碼樣例遇到了另外一個問題:它在用戶每次訪問頁面時都要求獲得 Google Calendar 事件摘要。如果把這個樣例放到 PHP 站點的側欄中,訪問者每次轉到任意一個頁面 ,代碼都將重新下載並解析摘要。考慮到日歷可能不會每個小時或者甚至每天都更改,這樣做是非常浪費的。如果您的站點非常受歡迎並且每天吸引 1,000 或更多頁面點擊率(只有 20 至 30 個惟一用戶的流行論壇即可輕松達到這個點擊率),則針對每次頁面點擊請求和處理摘要。Google 數據 API 有明確的服務條款,說明不允許執行此類應用。如果不遵守服務條款,Google 可以並且可能將攔截您服務器的 IP 地址。在更糟糕的情況下,Google 可以取消您的帳戶。很明顯,提倡使用一種更聰明的方法。

  有若干個可以實現的策略使樣例代碼更聰明地在 Google API 服務條款許可范圍內運行。這些策略全都涉及緩存腳本所顯示的信息以及僅當發生更改時才請求處理整個摘要。深入討論緩存技術不在本文討論范圍內,但是我將簡要討論緩存技術,讓您了解可以改進腳本的方法。

  一項技術涉及使用 HTTP 請求報頭檢查 Google 數據 API 摘要是否已更改。Google 數據服務將根據返回信息中的 <atom:updated> 元素的值設置 Last-ModifIEd 響應報頭。腳本在第一次被調用時可以將處理摘要所生成的輸出保存到 Html 文件中。腳本隨後可以把 <atom:updated> 時間戳的值存儲到數據庫記錄中。下一次任何用戶請求查看事件日歷時,客戶機都將檢索時間戳並把它發送回 If-ModifIEd-Since 請求報頭中,以避免在它未發生更改的情況下再次檢索摘要。

  如果自 If-Modified-Since 標頭中指示的時間後內容未發生更改,那麼 Google 數據服務將返回一個 304 (Not ModifIEd) HTTP 響應。由於這意味著事件數據未更改,因此腳本隨後可以包括 先前生成的 HTML 文件。如果摘要已更改,那麼 Google 數據服務將返回 200 (OK) HTTP 響應。在這種情況下,腳本將為 Html 文件重新生成新內容,將數據庫記錄設為 <atom:updated> 元素中的新時間戳值,並且包括 新生成的 Html 文件。

  把單個時間戳保存到數據庫中是非常多余的,但是 PHP 不像 Microsoft Active Server Page (ASP)、Microsoft ASP.Net、Java servlet 和 JavaServer Page (JSP) 一樣支持應用程序級變量,至少出廠時不支持。類似的解決方案是使用共享內存。並不是所有的 PHP 安裝都支持共享內存,因為它可能是安全風險隱患。另一種可能的緩存備選方法(尤其當 PHP 應用程序在 Web 服務器集群中運行時)是 memcached,它是最初由 LiveJournal 的創建者開發的集群內存緩存服務,現在已經被 FaceBook 的開發人員全面改進。

  結束語

  Google Calendar 提供了一個集中式 Web 應用程序前端,通過該前端,組織及其管理者可以不受限制地為其成員和公眾維護和發布事件日歷。Google 數據 API 提供了 Atom 摘要和 Atom 發布協議以使用 Google Calendar 和幾乎所有其他 Google 應用程序檢索、查詢、更新和創建事件和其他信息。

  使用 XPath,可以通過查詢 Google 數據 API 事件摘要並解析其條目以獲得條目元素之間的相關詳細信息,自動與 Web 站點顯示的最新事件保持同步。雖然 XPath 不是 PHP 工具包中速度最快的 XML API,但是當您手上擁有詳細記錄的 XML 文檔時它是其中最易於使用的。您可以使用緩存來減少 XPath 性能相對較慢的影響。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved