querypath_了解QueryPath PHP库

querypath

可以断定,在过去15年中,对Web爆炸性增长贡献最大的三项技术是HTML,HTTP和XML。 您可能会对此进行扩展,可能指向CSS,JavaScript和类似技术。 但是,“三巨头”仍然没有受到挑战。

PHP在Web开发领域也引起了轰动。 PHP为网站(从小型主页到Yahoo!之类的网站)提供动力,很大程度上是因为它易于开发和以Web为中心的模型。 但是,使用PHP与三巨头(尤​​其是XML)配合使用有时会很棘手。 在本文中,了解QueryPath,这是一个设计有两个目标PHP库:

  • 简单性,使其易于使用HTML,XML和HTTP
  • 健壮性,为使用这些技术提供丰富的工具

本文探讨了如何构建QueryPath对象,遍历XML和HTML,操纵XML和HTML以及使用QueryPath访问Web服务(Twitter是示例服务)。

下一节简要介绍了库及其设计。

查询路径

为简单起见,QueryPath使用一种紧凑的语法。 方法名称简短,代表了它们的作用(例如, text()append()remove() )。 由于大多数方法都返回QueryPath对象,因此方法调用是可链接的 ,这意味着可以按一个顺序调用多个方法。 这种约定有时称为流利接口 。 为了使JavaScript开发人员熟悉这些内容,QueryPath实现了大多数jQuery遍历和操纵功能以及行为。

为了健壮起见,QueryPath提供了旨在解决典型用例的工具,这些用例用于加载,搜索,读取和写入XML和HTML内容。 但是,不管库的大小如何,一个通用API都不能满足所有需求。 为了解决此问题,QueryPath包含扩展机制,可让您向QueryPath添加新方法。 QueryPath还包括扩展,以添加数据库支持,模板支持和其他XML功能。

您可能会想:“为什么要使用另一个XML或HTML工具?PHP V5已经具有少数XML工具,包括文档对象模型(DOM)实现和SimpleXML库。为什么要添加另一个?” 简短的答案:QueryPath被设计为通用工具。 DOM API既复杂又麻烦。 它的面向对象模型可能功能强大,但是即使是最简单的任务也可能需要数十行代码。 另一方面,对于许多编程任务而言,SimpleXML太简单了。 除非XML是完全可预测的,否则导航SimpleXML文档可能很简单。

QueryPath试图在DOM的功能丰富性和SimpleXML的简单性之间找到最佳结合点。

要求

QueryPath是一个纯PHP库。 要使用它,只需从官方网站下载它,并将其添加到您PHP库路径即可。

QueryPath具有最低的系统要求。 只要启用了DOM扩展,它就可以在PHP V5上运行。 PHP V5的大多数发行版都可以立即满足此要求。 QueryPath不支持早已弃用PHP V4。

QueryPath链的剖析

QueryPath的典型用法有四个核心概念:

  • QueryPath对象与单个XML或HTML文档相关联。
  • QueryPath可以查询文档,从而识别文档中的一组匹配项。
  • 可以通过QueryPath操作文档。 可以添加新零件,可以修改现有零件,并可以删除不需要的零件。
  • QueryPath方法可以链接在一起,以紧凑的顺序执行许多操作。 只需几行代码,即可加载,解析,查询,修改和编写文档。

清单1中的代码说明了所有这些要点。

清单1.基本的QueryPath链
<?php
require 'QueryPath/QueryPath.php';

qp('sample.html')->find('title')->text('Hello World')->writeHTML();
?>

上面的示例需要一个库QueryPath/QueryPath.php 。 这是使用QueryPath所需包含的唯一文件,除非您还正在加载QueryPath扩展。

该示例中的下一行代码是QueryPath链,它执行以下操作。

  1. 创建一个指向sample.html文档的新QueryPath对象。 运行qp() ,它将创建一个新的QueryPath对象,该对象随后将加载和解析文档。
  2. 使用find()方法,它使用级联样式表(CSS)3选择器title搜索文档,该选择器title搜索所有<title/>元素。

    在有效HTML文档中,这将仅与文档开头的单个<title/>元素匹配。

  3. 标题的文本值设置为Hello World 。 执行此操作后,标题的子节点将被CDATA(字符数据)字符串Hello World替换。 任何现有内容将被销毁。
  4. 整个文档将使用writeHTML()方法写入标准输出。

上面的示例实际上可以缩短一点,因为qp()工厂函数将CSS选择器作为可选的第二个参数。 清单2显示了缩短的版本。

清单2.基本QueryPath链的简化版本
<?php
require 'QueryPath/QueryPath.php';

qp('sample.html', 'title')->text('Hello World')->writeHTML();
?>

假设sample.html只是一个HTML基本文档,那么上述结果( 清单1或清单2)将类似于清单3。粗体行包含我们设置的标题。

清单3.生成HTML的示例
<!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可以执行的常规任务。 接下来的几节将探讨方法的系列。 之后,您将组装这些构件以创建一个简单的Web服务客户端。

qp()工厂函数

QueryPath库中最常用的函数是qp()工厂函数。 本质上,它执行创建新QueryPath对象的任务。 它用于支持传统的构造函数。

如果您熟悉面向对象的设计模式,则可能会将qp()识别为工厂模式的一种变体。 QueryPath不用使用builder方法定义工厂类,而只使用一个函数。 除了节省一些击键(在链接方法时很重要)之外,这种方法还使QueryPath距jQuery有点近,并且如果您熟悉jQuery,则可以减少学习曲线。

QueryPath对象将与单个XML或HTML文档关联。 构造对象时,文档将绑定到QueryPath对象。 qp()函数最多包含三个参数,所有参数都是可选的:

一个文件
可以是文件名或URL,XML或HTML字符串,DOMDocument或DOMElement,SimpleXMLElement或DOMElement数组。 如果此处未提供任何内容,则QueryPath将创建一个空XML文档进行操作。
CSS3选择器
如果提供了此选项,则QueryPath将在加载文档后使用给定的选择器查询该文档。
选项的关联数组
提供一种为QueryPath的特定实例传入一组复杂的配置参数的方法。 API参考详细说明了可以在此处传递的选项。

qp()的第一个参数采用了多种类型的数据,以使构造QueryPath对象变得容易。 QueryPath可以以文件名或URL开头并加载文档。 如果传入XML或HTML字符串,则QueryPath将解析内容。 而且,当然,它可以以XML文档的其他两种常见对象表示形式接收文档:DOM和SimpleXML。 清单4显示了qp()函数如何解析包含XML的字符串。

清单4.从XML字符串构建QueryPath对象
<?php
require 'QueryPath/QueryPath.php';

$xml = '<?xml version="1.0"?><doc><item/></doc>';
$qp  = qp($xml);
?>

运行清单4中的代码时, $qp将引用一个QueryPath对象,该对象内部指向XML的已解析表示形式。 前面的示例传递了文件名。 如果将PHP配置为允许HTTP / HTTPS流包装器(这在大多数PHP V5发行版中是标准的),则您甚至可以加载远程HTTP URL,如下所示。

清单5.从URL构建一个QueryPath对象
<?php
require 'QueryPath/QueryPath.php';

$qp = qp('http://example.com/file.xml');
?>

这样就可以使用QueryPath访问Web服务。 (可以使用第三个qp()参数传递流上下文,从而使您可以微调连接设置。)创建新文档时,有一个添加样板HTML的快捷方式,如下所示。

清单6.使用QueryPath::HTML_STUB常量
<?php
require 'QueryPath/QueryPath.php';

$qp = qp(QueryPath::HTML_STUB);
?>

QueryPath::HTML_STUB常量定义一个基本HTML文档,如下所示。

清单7. QueryPath::HTML_STUB文档
<?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>

从此框架文档开始,将使HTML生成更快。

至此,您知道了如何创建一个指向文档的新QueryPath对象,并且还看到了一个简单CSS选择器。 下一节将介绍如何使用QueryPath遍历文档。

遍历文档

打开文档后,您需要在文档内部四处移动以查找感兴趣的内容。 QueryPath旨在简化此过程。 为了满足许多遍历需求,QueryPath提供了几种遍历方法。 大多数允许使用CSS3选择器来查找所需的节点。

图1.重要的QueryPath遍历方法
重要的QueryPath遍历方法

图1总结了常用的遍历函数。 每个都在下面描述。 尽管还有其他遍历方法,但此处讨论的方法涵盖了大多数典型需求。

表1.常见的遍历方法
方法 描述 需要CSS选择器吗?
find() 选择与选择器匹配的任何元素(在当前选定的节点下)
xpath() 选择与给定XPath查询匹配的任何元素 否(改为使用XPath查询)
top() 选择文档元素(根元素) 没有
parents() 选择任何祖先元素
parent() 选择直接父元素
siblings() 选择所有兄弟姐妹(上一个和下一个)
next() 选择下一个同级元素
nextAll() 选择当前元素之后的所有同级
prev() 选择上一个同级
prevAll() 选择所有以前的兄弟姐妹
children() 选择此元素正下方的元素
deepest() 选择此节点下最深的一个或多个节点 没有

QueryPath中的许多方法都可以进行查询,以进一步指定应选择的项目。 如表1第三列所示,几乎所有这些方法都将CSS3选择器作为可选参数。 ( xpath()函数采用XPath查询而不是CSS3选择器。)仅top()deepest()不会将查询作为参数。

再看一个简单的例子,看看遍历是如何工作的。 假设您有一个XML文档,如下所示。

清单8.一个简单的XML文档
<?xml version="1.0"?>
<root>
  <child id="one"/>
  <child id="two"/>
  <child id="three"/>
  <ignore/>
</root>

<root/>元素有四个子元素:三个被命名为<child/> ,一个被命名为<ignore/> 。 您可以使用QueryPath查询选择<root/>所有四个子级。

清单9.选择所有子项
<?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对象中匹配项的数量,将打印4

假设您只想选择三个<child/>元素,而不要选择<ignore/>元素。 清单10显示了如何做到这一点。

清单10.使用过滤器查询
<?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当前选择的项目数。 它将返回3 。 在内部,QueryPath跟踪这三个匹配项。 它们存储为当前上下文。 如果您决定执行进一步的查询,则将从这三个元素开始。 如果您尝试追加数据,则数据将被追加到这三个元素。

CSS选择器

CSS选择器是CSS语句的一部分,用于选择要向其应用样式的元素。 CSS选择器也可以在样式表的上下文之外使用。 QueryPath使用选择器作为查询语言,并支持CSS3选择器标准中描述的功能集。

CSS选择器在QueryPath中扮演重要角色。 您已经看到10个以CSS选择器作为参数的函数。 到目前为止使用的选择器是简单的标签名称查询。 CSS3选择器比前面的示例所暗示的功能强大得多。 CSS3选择器的详细描述不在本文讨论范围之内,但是表2提供了常见选择器模式的示例。

表2.常见CSS3选择器模式
选择器模式 描述 比赛范例
p 查找标签名称为<p/>元素。 <p>
.container 查找class属性设置为container元素。 <div class =“ container” />
#menu 查找id属性设置为menu的元素。 这就是完成基于ID的搜索的方式。 <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>

这些常见的选择器模式可以组合以构建复杂的选择器,例如

div.content ul>li:first

该选择器将搜索具有类content任何<div/> 。 在div内部,它将搜索所有无序列表( <ul> ),并为每个列表返回第一个列表项( <li> )。

遍历匹配项

您已经了解了遍历文档的两个方面:QueryPath提供的方法和CSS3选择器支持。 第三个方面是遍历所选项目。

QueryPath对象是可遍历的 。 用PHP的话来说,这意味着可以将对象视为迭代器。 标准PHP循环结构可以循环遍历QueryPath对象的选定元素。 回想一下清单10中的示例,这是一个简单的查询,用于从XML文档中检索三个元素。 它用作下一个示例的基础。

如果要单独处理每个项目怎么办? 您可以轻松地做到这一点,因为QueryPath可以用作迭代器。 清单11显示了一个示例。

清单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;
}
?>

foreach循环迭代时,它将把每个匹配的元素分配给$child变量。 但是, $child不仅仅是元素。 它是指向当前元素的QueryPath对象。 您可以使用所有常用的QueryPath方法。

为了维护类似于jQuery的API,QueryPath提供了几种同时充当访问器和更改器(即getter和setter)的方法。 根据参数,单个方法可以检索(访问)数据或更改(变异)数据。 attr()函数就是一个示例。 qp()->attr('name')检索名称为name的属性的值。 qp()->attr('name', 'value')name属性的值设置为value 。 其他几种方法,包括text()html()xml() ,都作为访问器和更改器执行双重任务。

由于每个迭代项都包装在QueryPath对象中,因此可以使用$child处理所有标准QueryPath方法。 上面的示例使用attr()函数,该函数是元素属性的访问器和更改器。

attr()方法检索名为id的属性的值。 上面代码的输出如下所示。

清单12.清单11中的迭代器示例的输出
one
two
three

您已经了解了如何使用QueryPath方法,CSS3选择器和迭代技术来遍历文档。 下一节将探讨如何使用QueryPath修改文档。

处理文件

除了使用QueryPath搜索文档外,您还可以使用它来添加,修改和删除文档中的数据。 您在清单1中看到了QueryPath的功能。为方便起见,在下面重复进行。

清单13.基本的QueryPath链
<?php
require 'QueryPath/QueryPath.php';

qp('sample.html')->find('title')->text('Hello World')->writeHTML();
?>

在此示例中, text()函数用于修改<title/>元素的内容。 QueryPath提供了十几种更改文档的方法。 图2显示了几种常用的修改方法如何工作。 这些方法都添加或替换数据。 绿色标签表示当前选择的元素。

图2.用于添加或替换内容的QueryPath方法
用于添加或替换内容的QueryPath方法

每种方法通常以HTML或XML片段的形式获取字符串数据,然后将数据插入文档中。 然后,该数据立即可用于访问和进一步处理。

确实有两类方法代表。 在一个类中,某些方法可以处理XML的任意片段,如下所示。

处理HTML和XML片段
append() 将数据附加为当前所选元素的最后一个子元素
prepend() 将数据作为当前所选元素的第一个子元素添加
after() 在当前选定的一个或多个元素之后立即插入数据
before() 在当前选定的一个或多个元素之前插入数据
html() 替换HTML文档中当前元素的子内容
xml() 替换XML文档中当前元素的子内容

上面的项目需要一个包含一串格式正确的XML或HTML数据的参数。 清单14给出了html()方法的示例。

清单14.基本的QueryPath链
<?php
require 'QueryPath/QueryPath.php';

qp($file)->find('div.content')->html('<ul><li>One</li></ul>');
?>

图2中缺少remove()方法。 (删除很难用视觉方式表示。) remove()方法从文档中删除元素。 如果不带参数调用,它将删除当前选定的元素。 但是,与许多其他QueryPath方法一样, remove()将CSS3选择器作为可选参数。 提供选择器后,与选择器匹配的项目将被删除。

图2中的第二类方法包括操纵元素内属性的方法。 在示例中,显示了两个。

使用属性
attr() 获取值或为每个选定元素上的给定属性设置值。
addClass() 向当前选择中的每个元素添加一个类。

还有其他与属性相关的方法。 例如,以类名作为参数的removeClass()将从元素中删除单个类。 使用属性名称作为参数的removeAttr()将从所有当前选择的元素中删除命名属性。

现在是时候将所有这些基本功能整合到一些有趣的东西中了。

示例:使用QueryPath搜索Twitter

Twitter是一种流行的微博客服务,可让您在关注其他Twitter用户的微博的同时发布短信。 Twitter提供了一个简单的Web服务,它公开了平台的许多功能。

以下示例使用QueryPath在Twitter的服务器上执行搜索并将结果打印为HTML。 可以将这种工具添加到现有网站中,以显示有关感兴趣主题的最新Twitter活动。

Twitter的搜索服务器在标准HTTP服务器上进行侦听,并且可以(当被要求时)以Atom XML格式返回搜索结果。 我们的示例将搜索提及QueryPath的最新五个Twitter帖子。 要运行这样的搜索并以Atom格式返回内容,您只需要在URL中编码必要的信息: http://search.twitter.com/search. atom ? rpp=5 & q=QueryPathhttp://search.twitter.com/search. atom ? rpp=5 & q=QueryPath http://search.twitter.com/search. atom ? rpp=5 & q=QueryPath http://search.twitter.com/search. atom ? rpp=5 & q=QueryPath

粗体的三个部分代表针对此应用程序调整的参数。

.atom 包括此扩展名将向服务器指示您要返回Atom XML内容。
rpp=5 RPP用于每页结果。 我们希望返回五个结果。 默认情况下,将返回五个最新结果。
q=QueryPath 这是查询。 Twitter支持更复杂的搜索查询,但这只是此简短示例所需要的。

加载此URL后,Twitter将返回Atom格式的XML文档。 下面的清单15显示了返回文档的简化版本。 仅在此处显示您直接关注的信息(仅显示一个条目)。

清单15. Twitter搜索返回的XML摘录
<?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 &lt;b&gt;QueryPath&lt;/b&gt; (as
       extensions). Will commit them today.
    </content>
    <link type="image/png" rel="image" href="http://example.com/img.jpg"/>
    <author>
      <name>technosophos (M Butcher)</name>
      <uri>http://twitter.com/technosophos</uri>
    </author>
  </entry>
</feed>

清单16显示了简短的QueryPath代码,该代码执行搜索,筛选返回的XML并创建一个文档。

清单16.使用QueryPath处理返回的XML
<?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浏览器执行上述代码,则会看到类似图3的内容。

图3. QueryPath显示Twitter搜索结果
QueryPath显示Twitter搜索结果

清单16中的代码长14行,而工作仅用9行完成。 该代码如何转换为图3中的视图?

$url变量保存您先前检查过的Twitter URL。 $out变量指向用于将HTML写入客户端的QueryPath对象。 从基本文档( QueryPath::HTML_STUB )开始,您将添加无序列表,然后(使用find() )选择该新列表。

foreach循环是脚本中最重要的一行: foreach (qp($url, 'entry') as $result) 。 在这里,创建了一个新的QueryPath对象。 由于传入了URL,因此QueryPath将检索远程Atom文档并解析结果。 并且,由于传入了选择器entry ,因此QueryPath将选择文档中的所有条目。 回头看看清单15 ,以了解这是文档的哪一部分。 返回的文档中将有五个条目(因为这是在URL中设置rpp标志的方式)。 五个条目中的每一个都应类似于清单15中的<entry/>

在循环内部,获取了三个数据:

$title 条目内容
$img 发布用户的个人资料图片的网址
$author 发布用户的名称

要检索数据的每一位,可以使用各种QueryPath方法。 例如,您可以使用$result->children('content')->text();获得$title $result->children('content')->text();

这首先选择具有标签名称content所有子项,然后从找到的节点中获取CDATA文本。 每个条目将具有一个<content/>元素。

现在您需要获取图像URL。 在上一个链中,选择了<content/>元素,因此这是起点。 您需要在<content/>的同级中搜索看起来像<link rel="image"/>的元素。 为此,请将siblings()函数与选择器一起使用。 然后使用attr()函数获取元素的href属性的值。

最后,从<link/>元素跳转到其父元素,然后使用find('author>name') 。 (有关其工作原理,请参见表2。 )从那里,您可以使用text()获得作者姓名的text()

foreach循环的每次迭代结束时,您将构建HTML片段,并使用append()将其插入到$out QueryPath中。

对来自Twitter的结果进行迭代之后,可以通过将HTML文档写入浏览器来包装脚本: $out->writeHTML();

你有它。 在大约十二行代码中,您已经与远程Web服务接口。 QueryPath可以这种方式用于访问几乎所有使用HTTP和XML或HTML的Web服务。 QueryPath附带的示例说明了如何设置连接参数,如何对SPARQL端点执行SPARQL查询以及如何解析复杂的,多命名空间的文档。 QueryPath为使用Web服务提供了巨大的潜力。

结论

在本文中,您探索了QueryPath库的基础。 您学习了如何创建QueryPath对象,遍历文档和操作内容。 您还构建了一个小示例脚本,该脚本可与流行的Twitter微博服务的Web服务API一起使用。

本文只是开始挖掘QueryPath库的可能性。 例如,仅提及数据库API,该API可用于将RDBMS支持集成到QueryPath中。 想象一下,运行一条SQL SELECT语句并将结果直接合并到标记为您的规范HTML表中。 或者想象构建一个XML导入器,该导入器可以解析数据并将其直接插入数据库中。

QueryPath的其他功能甚至都没有提到。 使用映射器和过滤器,您可以让QueryPath运行自定义函数来转换或过滤QueryPath数据。 使用QPTPL扩展,您可以将数据合并到预定义的纯HTML模板中。 QueryPath还支持用户定义的扩展。 通过编写简单的类定义,可以将自己的方法添加到QueryPath。


翻译自: https://www.ibm.com/developerworks/opensource/library/os-php-querypath/index.html

querypath

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值