?
?
紅得發(fā)紫的jQuery框架是專門用于頁面Javascript程序設(shè)計的,它通過一種優(yōu)雅的方式讓我們輕松自如地操作頁面的所有元素而無須擔(dān)心瀏 覽器版本以及兼容性等問題。受到j(luò)Query的啟發(fā),一種試圖讓W(xué)eb開發(fā)者在PHP中直接采用jQuery方式操縱和生成HTML/XML元素的 QueryPath計劃開始了,庫的發(fā)開者是 Matt Butcher 。
?
QueryPath可以很方便地讀入和生成HTML/XML,使用jQuery類似的語法和函數(shù)遍歷文檔對象,支持遠(yuǎn)程URL文件的讀取和分析。支 持標(biāo)準(zhǔn)的CSS3 Selector和XPath,這意味著我們可以使PHP像jQuery一樣,隨心所欲地玩轉(zhuǎn)任何HTML!當(dāng)然PHP5本身就帶了不少DOM解析 庫,QueryPath本身也是在這些庫上的二次加工,省下了我們不少的工作量。
QueryPath官方網(wǎng)站: http://querypath.org/
?
QueryPath使用一個qp()工廠函數(shù),為各種需求生成不同的類,一個最簡單的例子如下:
?
require 'QueryPath/QueryPath.php'; $html = qp('a.html'); $html->find('title')->text('hello world'); $html->find('.myInput')->attr('value', 'hello world'); $html->find('body')->css('background-color', 'red');?
如果你對jQuery熟悉的話,幾乎可以沒有任何學(xué)習(xí)成本就能很快上 手。我立刻就使用QueryPath來寫了幾個測試?yán)蹋治龊捅闅v了一個常去的網(wǎng)站的內(nèi)容結(jié)構(gòu),抓取了和分析了不少有用的資料。感覺對于那些做網(wǎng)站采集 程序的家伙們來說,QueryPath是不是又要讓他們更加如魚得水(抑或是無惡不作)了,LOL。
?
使用過程中發(fā)現(xiàn)QueryPath庫尚處于基本的開發(fā)狀態(tài),不少問題。但對于程序員來說,遇到問題讀一下庫的源代碼,基本上就能搞定。下面列出兩個 常用問題的解決,與大家分享。
?
1.當(dāng)QueryPath查詢到一個節(jié)點并操作完成后,它本身并不回到根節(jié)點,而是停留在節(jié)點上,不知道這樣描述正確否,這樣導(dǎo)致的結(jié)果是下一步的 查詢將很可能找不到數(shù)據(jù)。解決的方法是用top()函數(shù)回到根節(jié)點。如上面的例子可以直接這樣用,用top回到根:
?
$html->top()->find('.myInput')->attr('value', 'hello world');?
支持的方法有top(), prev(), next(), child(),不用解釋,很好理解。
?
?
2.無法讀取遠(yuǎn)程url,或不能識別非"html"的擴(kuò)展名的html文件。QueryPath直接分析文件和url的擴(kuò)展名,不為"html"的直接當(dāng)做xml處理,寒一個。解決的辦法是用url的傳遞參數(shù)在最后面?zhèn)窝b一 個".html"的參數(shù),告訴QueryPath這是HTML文件。解決方法:
?
$qp('http://www.acwind.net/index.php?=.html');//偽裝一個后綴名,搞定。?
希望開發(fā)者能在將來的版本中改進(jìn),能自動識別文件類型那該多好。
詳解:
?
PHP 也曾在 Web 開發(fā)領(lǐng)域造成轟動。由于易于開發(fā)和以 Web 為中心的模型,PHP 使 Web 站點從小小的主頁變成像 Yahoo! 這樣強(qiáng)大的站點。但是,通過 PHP 來使用這三種技術(shù) — 尤其是 XML — 有時候會比較復(fù)雜。在本文中,了解 QueryPath,這是一個 PHP 庫,它在設(shè)計時考慮了兩個目標(biāo):
- 簡單性,使 HTML、XML 和 HTTP 變得容易使用
- 健壯性,為使用這些技術(shù)提供豐富的工具
本文探索如何構(gòu)建 QueryPath 對象、遍歷 XML 和 HTML、操縱 XML 和 HTML 以及使用 QueryPath 訪問 Web 服務(wù)(使用 Twitter 作為示例服務(wù))。
?
?
對于 QueryPath 的典型使用,有四個最重要的概念:
- QueryPath 對象與一個 XML 或 HTML 文檔相關(guān)聯(lián)。
- QueryPath 可以查詢文檔,識別文檔中的一組匹配項。
- QueryPath 可以操縱文檔??梢蕴砑有碌牟糠?,修改已有的部分,刪除不想要的部分。
- QueryPath 方法可以鏈接在一起,在一個簡潔的序列中執(zhí)行很多操作。只需幾行代碼,就可以裝載、解析、查詢、修改和寫入文檔。
清單 1 中的代碼展示了所有這些要點。
?
<?php require 'QueryPath/QueryPath.php'; qp('sample.html')->find('title')->text('Hello World')->writeHTML(); ?>? ?
以上例子需要一個庫,即
QueryPath/QueryPath.php
。除非還要裝載 QueryPath 擴(kuò)展,否者只需包括這個庫就可以使用 QueryPath。
![]() |
|
例子中接下來一行代碼是一個 QueryPath 鏈,它做以下事情。
-
創(chuàng)建一個新的
QueryPath
對象,該對象指向 sample.html 文檔。當(dāng)qp()
運行時,它將創(chuàng)建一個新的QueryPath
對象,后者隨即裝載和解析文檔。 -
使用
find()
方法,它使用 CSS 3 選擇器title
搜索整個文檔,尋找所有<title/>
元素。在一個有效的 HTML 文檔中,該搜索只能在文檔的頭部找到一個匹配的
<title/>
元素。 -
標(biāo)題的文本值被設(shè)為
Hello World
。當(dāng)執(zhí)行到這里時,標(biāo)題的子節(jié)點將被 CDATA(字符數(shù)據(jù))字符串Hello World
替換。任何已有的內(nèi)容將被破壞。 -
使用
writeHTML()
方法將整個文檔寫到標(biāo)準(zhǔn)輸出中。
以上例子實際上還可以縮短一點,因為
qp()
工廠函數(shù)帶有一個 CSS 選擇器作為可選的第二個參數(shù)。清單 2 顯示了縮短后的版本。
?
<?php require 'QueryPath/QueryPath.php'; qp('sample.html', 'title')->text('Hello World')->writeHTML(); ?>? |
?
假設(shè)
sample.html
是一個最基本的 HTML 文檔,以上代碼(
清 單 1
或清單 2)的結(jié)果看上去將如清單 3 所示。加粗的行包含我們設(shè)置的標(biāo)題。
?
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <title>Hello World</title> </head> <body> </body> </html>? |
?
這些簡單的例子展示了 QueryPath 可以執(zhí)行的一些常見的任務(wù)。接下來幾個小節(jié)探索一些方法。然后,您將把這些構(gòu)建塊裝配起來,創(chuàng)建一個簡單的 Web 服務(wù)客戶機(jī)。
?
?
QueryPath 庫中最常用的函數(shù)是
qp()
工廠函數(shù)。實際上,它執(zhí)行創(chuàng)建新的 QueryPath 對象的任務(wù)。它被用于傳統(tǒng)的構(gòu)造函數(shù)。
?
如果您熟悉面向?qū)ο笤O(shè)計模式,那么可能會意識到
qp()
是工廠模式的一個變種。 QueryPath 不是用構(gòu)造器方法定義一個工廠類,而是使用一個函數(shù)。這種方法除了可以節(jié)省鍵盤輸入外(在鏈接方法時比較重要),還可以使 QueryPath 更貼近 jQuery,減少 jQuery 熟悉者的學(xué)習(xí)曲線。
?
一個
QueryPath
對象與一個 XML 或 HTML 文檔相關(guān)聯(lián)。當(dāng)構(gòu)造
QueryPath
對象時,文檔被綁定到該對象。
qp()
函數(shù)帶有 3 個參數(shù),這 3 個參數(shù)都是可選的:
![]() |
|
qp()
支持將很多類型的數(shù)據(jù)作為第一個參數(shù),從而方便構(gòu)建 QueryPath 對象。QueryPath 可以以一個文件名或 URL 開始,然后裝載一個文檔。如果傳遞的是一個 XML 或 HTML 字符串,QueryPath 將解析該內(nèi)容。當(dāng)然,它可以接受另外兩種常用的 XML 文檔的對象表示:DOM 和 SimpleXML。清單 4 展示
qp()
函數(shù)如何解析包含 XML 的字符串。
清單 4. 從 XML 字符串構(gòu)建 QueryPath 對象
?
<?php require 'QueryPath/QueryPath.php'; $xml = '<?xml version="1.0"?><doc><item/></doc>'; $qp = qp($xml); ?>? |
?
當(dāng)清單 4 中的代碼運行時,
$qp
將引用一個
QueryPath
對象,該對象在內(nèi)部指向 XML 解析后的表示。前面的例子傳入的是一個文件名。如果 PHP 被配置為允許 HTTP/HTTPS 流包裝器(在大多數(shù) PHP V5 發(fā)行版中是標(biāo)準(zhǔn)配置),那么甚至可以裝載遠(yuǎn)程 HTTP URL,如下所示。
清單 5. 從 URL 構(gòu)建 QueryPath 對象
?
<?php require 'QueryPath/QueryPath.php'; $qp = qp('http://example.com/file.xml'); ?>? |
?
這樣便可以使用 QueryPath 訪問 Web 服務(wù)。(可以使用第 3 個參數(shù)
qp()
傳遞流上下文,以便對連接設(shè)置進(jìn)行調(diào)整)。當(dāng)創(chuàng)建新文檔時,有一個添加樣板 HTML 的快捷方式,如下所示。
清單 6. 使用
QueryPath::HTML_STUB
常量
?
<?php require 'QueryPath/QueryPath.php'; $qp = qp(QueryPath::HTML_STUB); ?>? |
?
QueryPath::HTML_STUB
常量定義一個基本的 HTML 文檔,如下所示。
?
<?xml version="1.0"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Untitled</title> </head> <body></body> </html>? |
?
以這個框架文檔為基礎(chǔ),可以更快地生成 HTML。
至此,您知道了如何創(chuàng)建新的指向文檔的 QueryPath 對象,并且看到了一個簡單的 CSS 選擇器。下一小節(jié)討論如何使用 QueryPath 遍歷文檔。
?
?
打開文檔后,需要在文檔中查找感興趣的內(nèi)容。QueryPath 的設(shè)計使得這一任務(wù)變得很容易。為了簡化遍歷需求,QueryPath 提供了一些用于遍歷的方法。大多數(shù)方法使用 CSS3 選擇器查找所需的節(jié)點。
圖 1 總結(jié)了常用的遍歷函數(shù)。下面一一描述每個函數(shù)。雖然還有一些遍歷函數(shù)沒有提到,但這里覆蓋了大多數(shù)常見的需求。
?
方法 描述 是否帶 CSS 選擇器
find()
|
選擇與選擇器匹配的任何元素(在當(dāng)前選擇的節(jié)點下) | 是 |
xpath()
|
選擇與給定 XPath 查詢匹配的元素 | 否(使用 XPath 查詢) |
top()
|
選擇文檔元素(根元素) | 否 |
parents()
|
選擇任何祖先元素 | 是 |
parent()
|
選擇直接父元素 | 是 |
siblings()
|
選擇所有同胞(sibling)元素(包括之前和之后的元素) | 是 |
next()
|
選擇后一個同胞元素 | 是 |
nextAll()
|
選擇當(dāng)前元素之后的所有同胞元素 | 是 |
prev()
|
選擇前一個同胞元素 | 是 |
prevAll()
|
選擇當(dāng)前元素之前的所有同胞元素 | 是 |
children()
|
選擇當(dāng)前元素的直接子元素 | 是 |
deepest()
|
選擇當(dāng)前元素下最深的節(jié)點 | 否 |
?
QueryPath 中的很多方法可以以查詢作為參數(shù),進(jìn)一步指定應(yīng)該選擇什么項。如表 1 中第三列所示,幾乎所有這些方法都帶有一個作為可選參數(shù)的 CSS3 選擇器。(
xpath()
函數(shù)則帶有一個 XPath 查詢,而不是 CSS3 選擇器)。只有
top()
和
deepest()
不使用查詢作為參數(shù)。
可以通過另一個簡單的例子了解如何進(jìn)行遍歷。假設(shè)有一個像下面這樣的 XML 文檔。
?
<?xml version="1.0"?> <root> <child id="one"/> <child id="two"/> <child id="three"/> <ignore/> </root>? |
?
<root/>
元素有 4 個子元素:其中有 3 個名為
<child/>
,還有一個名為
<ignore/>
。可以用一個 QueryPath 查詢選擇
<root/>
的所有 4 個子元素。
?
<?php require 'QueryPath/QueryPath.php'; $xml = '<?xml version="1.0"?> <root> <child id="one"/> <child id="two"/> <child id="three"/> <ignore/> </root>'; $qp = qp($xml, 'root')->children(); print $qp->size(); ?>? |
?
children()
方法將選擇
<root/>
元素的所有直接子元素。最后一行打印
QueryPath
對象中匹配項的數(shù)量,最終打印的結(jié)果為
4
。
假設(shè)只需選擇 3 個
<child/>
元素,而不需要選擇
<ignore/>
元素。 清單 10 顯示了如何實現(xiàn)這一點。
?
<?php require 'QueryPath/QueryPath.php'; $xml = '<?xml version="1.0"?> <root> <child id="one"/> <child id="two"/> <child id="three"/> <ignore/> </root>'; $qp = qp($xml, 'root')->children('child'); print $qp->size(); ?>? |
?
最后的
print
語句將打印 QueryPath 當(dāng)前選擇的項的數(shù)量。它將返回
3
。在內(nèi)部,QueryPath 跟蹤這 3 個元素。它們被存儲為當(dāng)前上下文。如果執(zhí)行進(jìn)一步的查詢,那么查詢將從這 3 個元素開始。如果試圖附加數(shù)據(jù),那么數(shù)據(jù)將被附加到這 3 個元素后。
![]() |
|
CSS 選擇器是 CSS 語句的一部分,用于選擇將應(yīng)用某種樣式的元素。CSS 選擇器還可以在樣式表上下文之外使用。QueryPath 使用選擇器作為查詢語言,并支持 CSS3 選擇器 標(biāo) 準(zhǔn) 中描述的特性集。
CSS 選擇器在 QueryPath 中扮演很重要的角色。您已經(jīng)看到,有 10 個函數(shù)使用 CSS 選擇器作為參數(shù)。到目前為止使用的選擇器是簡單的標(biāo)記名查詢。CSS3 選擇器要比前面的例子強(qiáng)大得多。對 CSS3 選擇器的詳細(xì)描述超出了本文的范圍,但表 2 提供了一些常見的選擇器模式的例子。
選擇器模式 描述 示例匹配項
p
|
找到標(biāo)記名為
<p/>
的元素
|
<p> |
.container
|
找到
class
屬性被設(shè)為
container
的元素
|
<div class="container"/> |
#menu
|
找到
id
屬性被設(shè)為
menu
的元素?;?ID 的搜索以這種方式進(jìn)行
|
<div id="menu"/> |
[type="inline"]
|
找到
type
屬性的值為
inline
的元素
|
<code type="inline"/> |
tr > th
|
找到直接父元素為
<tr>
的
<th>
元素
|
<tr><th/></tr> |
table td
|
找到祖先(例如父親或祖父)中有
<table>
元素的
<td>
元素
|
<table><tr><td/></tr></table> |
li:first
|
獲取第一個名為
<li/>
的元素。支持的偽類包括
:last
、
:even
和
:odd
|
<li/> |
RDF|seq
|
找到
<RDF:seq>
元素。 QueryPath 包括用于 XML 名稱空間的 CSS3 選擇器。名稱空間支持延伸到屬性和元素
|
<RDF:seq> |
?
這些常見的選擇器模式可以加以組合,形成復(fù)雜的選擇器,例如
?
div.content ul>li:first? |
。 這個選擇器將搜索 class 為
content
的任何
<div/>
。 在
div
中,它將搜索所有無序列表(
<ul>
),返回每個列表的第一個列表項(
<li>
)。
?
?
您了解了遍歷文檔的兩個方面:QueryPath 提供的方法和 CSS3 選擇器支持。第三個方面是迭代選擇的項。
QueryPath 對象是 可遍歷的(traversable) 。在 PHP 中,這意味著對象可以當(dāng)做迭代器。標(biāo)準(zhǔn)的 PHP 循環(huán)結(jié)構(gòu)可以遍歷 QueryPath 對象選擇的元素。還記得嗎, 清 單 10 中的例子是一個簡單的查詢,它從一個 XML 文檔中檢索 3 個元素。接下來的例子將以這個例子為基礎(chǔ)。
如果要單獨處理每個項,應(yīng)該怎么辦?很容易,因為 QueryPath 可以用作迭代器。清單 11 顯示了一個例子。
?
<?php require 'QueryPath/QueryPath.php'; $xml = '<?xml version="1.0"?> <root> <child id="one"/> <child id="two"/> <child id="three"/> <ignore/> </root>'; $qp = qp($xml, 'root')->children('child'); foreach ($qp as $child) { print $child->attr('id') . PHP_EOL; } ?>? |
?
當(dāng)
foreach
循環(huán)迭代時,它將每個匹配項賦給
$child
變量。但是,
$child
不是真正的元素,它是指向當(dāng)前元素的一個
QueryPath
對象。您可以任意使用所有常見的 QueryPath 方法。
?
為了使 API 與 jQuery 的 API 類似, QueryPath 提供一些可同時作為 accessor 和 mutator — 或 getter 和 setter 的方法。取決于參數(shù),同一個方法可以檢索(access)數(shù)據(jù),或者更改(mutate)數(shù)據(jù)。
attr()
函數(shù)就是一個例子。
?
qp()->attr('name')
檢索
name
屬性的值。
qp()->attr('name', 'value')
將
name
屬性的值設(shè)為
value
。還有一些方法,包括
text()
、
html()
和
xml()
,作為 accessor 和 mutator 同時執(zhí)行兩種任務(wù)。
?
由于每個迭代的項包裝在一個 QueryPath 對象中,所以可以通過
$child
任意使用所有標(biāo)準(zhǔn)的 QueryPath 方法。上面的例子使用了
attr()
函數(shù),這是一個元素中的屬性的 accessor 和 mutator。
attr()
方法檢索名為
id
的屬性的值。下面顯示以上代碼的輸出。
?
one two three? |
?
您已經(jīng)了解了如何使用 QueryPath 方法、CSS3 選擇器和迭代技術(shù)遍歷文檔。下一節(jié)探索如何用 QueryPath 修改文檔。
?
?
除了使用 QueryPath 搜索文檔外,還可以使用它添加、修改和移除文檔中的數(shù)據(jù)。在清單 1 中可以大致了解 QueryPath 的功能。為了方便,下面再重復(fù)一遍。
?
<?php require 'QueryPath/QueryPath.php'; qp('sample.html')->find('title')->text('Hello World')->writeHTML(); ?>? |
?
在這個例子中,
text()
函數(shù)用于修改
<title/>
元素的內(nèi)容。QueryPath 提供了十幾個用于更改文檔的方法。圖 2 展示一些常用的修改方法如何工作。這些方法都是添加或替換數(shù)據(jù)。綠色的標(biāo)記表示當(dāng)前被選中的元素。
圖 2. 用于添加或替換內(nèi)容的 QueryPath 方法
每個方法以字符串?dāng)?shù)據(jù)(通常是以 HTML 或 XML 片段的形式)作為參數(shù),并將數(shù)據(jù)插入到文檔中。隨后立即可以訪問和進(jìn)一步操縱新插入的數(shù)據(jù)。
?
實際上有兩類方法。第一類方法使用任意的 XML 片段,如下所示。
append()
|
將數(shù) 據(jù)添加為當(dāng)前選中元素的 最后一個 子元素 |
prepend()
|
將 數(shù)據(jù)添加為當(dāng)前選中元素的 第一個 子元素 |
after()
|
將 數(shù)據(jù)直接插在當(dāng)前選中元素 之后 |
before()
|
將數(shù)據(jù)直接插在當(dāng)前選擇的元素 之前 |
html()
|
替換 HTML 文檔中當(dāng)前元素的子內(nèi)容 |
xml()
|
替換 XML 文檔中當(dāng)前元素的子內(nèi)容 |
?
以上方法需要一個參數(shù),該參數(shù)包含一個格式良好的 XML 或 HTML 數(shù)據(jù)的字符串。清單 14 有一個使用
html()
方法的例子。
?
<?php require 'QueryPath/QueryPath.php'; qp($file)->find('div.content')->html('<ul><li>One</li></ul>'); ?>? |
?
圖 2
中沒有給出
remove()
方法(難以清楚地表示移除)。
remove()
方法移除文檔中的元素。如果不帶參數(shù)調(diào)用,該方法將移除當(dāng)前選中的元素。但是,和很多其他的 QueryPath 方法一樣,
remove()
可以使用一個 CSS3 選擇器作為可選參數(shù)。如果提供了一個選擇器,那么只移除與選擇器匹配的項。
?
圖 2 中的第二類方法則操縱元素中的屬性。下面介紹兩個這樣的例子。
attr()
|
獲取或設(shè) 置每個選中的元素上給定屬性的值 |
addClass()
|
為當(dāng)前選中的每 個元素添加一個類 |
?
還有其他一些與屬性相關(guān)的方法。例如
removeClass()
方法,該方法以一個類名作為參數(shù),它將移除元素中的一個類。
removeAttr()
以一個屬性名作為參數(shù),它將從所有當(dāng)前選中的元素中移除具有該名稱的屬性。
現(xiàn)在可以將所有這些基本功能組合到一起,形成有趣的東西。
?
?
Twitter 是一個流行的微博客服務(wù),通過它可以發(fā)布短消息,同時還可以跟隨其他 Twitter 用戶的微博客。 Twitter 提供了一個簡單的 Web 服務(wù),用于公布該平臺的很多特性。
?
下面的例子使用 QueryPath 在 Twitter 服務(wù)器上執(zhí)行搜索,并以 HTML 格式打印結(jié)果??梢詫⒁粋€工具添加到已有的 Web 站點,以顯示最近的關(guān)于一個感興趣的話題的 Twitter 活動。
?
Twitter 的搜索服務(wù)器偵聽一個標(biāo)準(zhǔn)的 HTTP 服務(wù)器,當(dāng)被請求時,以 Atom XML 格式返回搜索結(jié)果。我們的例子將搜索最近 5 個提到 QueryPath 的貼子。為了運行這種搜索,并以 Atom 格式返回內(nèi)容,只需在 URL 中編寫必要的信息:
http://search.twitter.com/search.
atom
?
rpp=5
&
q=QueryPath
。
加粗的 3 個部分表示針對這個應(yīng)用程序進(jìn)行了調(diào)整的參數(shù)。
?
.atom
|
提供這個擴(kuò) 展名是為了告訴服務(wù)器需要返回 Atom XML 內(nèi)容 |
rpp=5
|
RPP 指定每頁顯示的結(jié)果數(shù)。我們想要返回 5 條結(jié)果。默認(rèn)情況下,將返回 5 條最近的結(jié)果 |
q=QueryPath
|
這 是查詢。Twitter 支持更復(fù)雜的搜索查詢,但對于這個簡單的例子只需要這樣的查詢。 |
?
當(dāng)裝載這個 URL 時,Twitter 將返回一個 Atom 格式的 XML 文檔。下面的清單 15 顯示一個經(jīng)過大量簡化的返回文檔。這里只顯示最關(guān)心的信息(只顯示一個條目)。
?
<?xml version="1.0" encoding="UTF-8"?> <feed> <entry> <content type="html"> Last night I added XSD schema validation and XSL Transformation (XSLT) support to <b>QueryPath</b> (as extensions). Will commit them today. </content> <link type="image/png" rel="image" /> <author> <name>technosophos (M Butcher)</name> <uri>http://twitter.com/technosophos</uri> </author> </entry> </feed>? |
?
清單 16 顯示了執(zhí)行搜索的簡要的 QueryPath 代碼,處理返回的 XML,并創(chuàng)建一個文檔。
?
<?php require 'QueryPath/QueryPath.php'; $url = 'http://search.twitter.com/search.atom?rpp=5&q=QueryPath'; $out = qp(QueryPath::HTML_STUB, 'body')->append('<ul/>')->find('ul'); foreach (qp($url, 'entry') as $result) { $title = $result->children('content')->text(); $img = $result->siblings('link[rel="image"]')->attr('href'); $author = $result->parent()->find('author>name')->text(); $out->append("<li><img src='$img'/> <em>$author</em><br/>$title</li>"); } $out->writeHTML(); ?>? |
?
如果使用 Web 瀏覽器執(zhí)行以上代碼,可以看到圖 3 所示的結(jié)果。
圖 3. QueryPath 顯示 Twitter 搜索結(jié)果
清 單 16 中的代碼有 14 行,其中只有 9 行代碼做實際的工作。以上代碼是如何產(chǎn)生圖 3 中的視圖的呢?
?
$url
變量存放前面提到的 Twitter URL。
$out
變量指向用于將 HTML 寫到客戶機(jī)的 QueryPath 對象。 從一個基本的文檔 (
QueryPath::HTML_STUB
)開始,添加一個無序列表,并(使用
find()
) 選擇這個新列表。
?
foreach
循環(huán)是腳本中最重要的一行:
foreach (qp($url, 'entry') as $result)
。這里創(chuàng)建 一個新的
QueryPath
對象。由于傳遞了一個 URL,QueryPath 將檢索遠(yuǎn)程 Atom 文檔,并解析結(jié)果。另外,由于傳遞了選擇器
entry
,QueryPath 將選擇文檔中的所有條目?;仡^查看一下
清 單 15
,看看這是文檔中的哪個部分。返回的文檔中將有 5 個條目(因為 URL 中這樣設(shè)置了
rpp
標(biāo)志)。這 5 個條目中的每個條目看上去都應(yīng)該與清單 15 中的
<entry/>
類似。
?
循環(huán)獲取了 3 個數(shù)據(jù)部分:
$title
|
條目的內(nèi) 容 |
$img
|
發(fā)帖用戶的頭像的 URL |
$author
|
發(fā) 帖用戶的用戶名 |
?
為了獲取每塊數(shù)據(jù),可以使用不同的 QueryPath 方法。例如,可以使用
$result->children('content')->text();
獲得
$title
。
?
![]() |
|
循環(huán)中首先選擇標(biāo)記名為
content
的所有子元素,然后從發(fā)現(xiàn)的節(jié)點中獲得 CDATA 文本。每個條目將有一個
<content/>
元素。
?
現(xiàn)在需要獲得圖像 URL。在前面的鏈中,選擇了
<content/>
元素,所以這就是起點?,F(xiàn)在需要搜索
<content/>
的同胞,找到形如
<link rel="image"/>
的元素。 為此,使用
siblings()
函數(shù),并提供一個選擇器作為參數(shù)。然后使用
attr()
函數(shù)獲得元素的
href
屬性的值。
?
最后,從
<link/>
元素跳回到它的父元素,接著使用
find('author>name')
, 獲得作者的用戶名。(請查看
表 2
)。在這里,可以使用
text()
獲得作者的用戶名的文本。
?
在
foreach
循環(huán)的每次迭代的最后,構(gòu)建一個 HTML 片段,并使用
append()
將這個片段插入到
$out
QueryPath 中。
?
迭代完從 Twitter 返回的結(jié)果后,可以在腳本的最后將 HTML 文檔寫到瀏覽器:
$out->writeHTML();
。
這樣就完成了。在大約十幾行代碼中,您完成了與一個遠(yuǎn)程服務(wù)的交互。可以通過這種方式,使用 QueryPath 訪問任何使用 HTTP 和 XML 或 HTML 的 Web 服務(wù)。QueryPath 附帶的例子展示了如何設(shè)置連接參數(shù)、對 SPARQL 端點執(zhí)行 SPARQL 查詢以及解析復(fù)雜的、多名稱空間的文檔。QueryPath 為使用 Web 服務(wù)帶來巨大的潛力。
?
?
?
在本文中,您探索了 QueryPath 庫的基礎(chǔ)。您學(xué)習(xí)了如何創(chuàng)建
QueryPath
對象、遍歷文檔和操縱內(nèi)容。您還構(gòu)建了一個小型的例子腳本,該腳本使用流行的 Twitter 微博客服務(wù)的 Web 服務(wù) API。
?
本文只是初步發(fā)掘 QueryPath 庫的一些可能的應(yīng)用。例如,本文只提到數(shù)據(jù)庫 API,可使用該 API 將 RDBMS 支持集成到 QueryPath。想象一下,運行一個 SQL
SELECT
語句,并將結(jié)果直接合并到一個符合自己的規(guī)范的 HTML 表格中。或者再想象一下,構(gòu)建一個 XML 導(dǎo)入器,用于解析數(shù)據(jù)并將數(shù)據(jù)直接插入到數(shù)據(jù)庫中。
?
QueryPath 還有一些特性這里沒有提到。通過映射器和過濾器,可以讓 QueryPath 運行定制的函數(shù)來轉(zhuǎn)換或過濾 QueryPath 數(shù)據(jù)。通過
QPTPL
擴(kuò)展,可以將數(shù)據(jù)插入到預(yù)定義的純 HTML 模板中。QueryPath 還支持用戶定義的擴(kuò)展。通過編寫一個簡單的類定義,可以將自己的方法添加到 QueryPath 中。
?
?
>>phpQuery—基于 jQuery的PHP實現(xiàn)
?
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
