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

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