php 使用xpath
在本文中,了解以下概念:
本文提供了几个可以结合使用XPath和PHP的工作示例,并假设您具有Prerequisites中描述的先决条件 。
为了从本文中获得最大收益,您应该具有XML和PHP5知识以及配置和安装PHP扩展。 此外,您还需要访问并了解带有支持PHP5的Web服务器的基于UNIX®或Microsoft®Windows®操作系统的知识,并可以在本文上练习本文中的代码示例。
随着Web向语义Web的原始愿景发展,应用程序之间的交互性也越来越强。 诸如SOAP,REST,RSS,RDF之类的技术以及其他技术是未来Web的强大推动者。 在大多数情况下,XML是用来描述所涉及数据的选定消息格式。 在某种程度上,您可以使用JSON,但您可能会将XML视为主要的数据交换方法。
或者,您可能会遇到将XML数据转换为XHTML,以为移动用户和各种Web浏览器提供有吸引力的,交互式的和可用的界面的任务。
将数据作为XML文档存储到文件系统或XML兼容数据库也是一种流行的方式来存档数据,以供以后检索以执行报告,用户界面显示或应用程序集成等任务。
使用XML数据时,您需要解析数据以获取最小公分母-所需数据(或原子节点值,通常称为原子节点值)。 XSLT是W3C标准,它执行XML到另一种格式的转换,例如HTML,PDF,甚至是另一种使用不同模式的XML文档。 XQuery,XForms和XPointer都非常依赖XPath的使用。
以最简单的形式,XPath是一种用于在内存中导航XML树的语言。 最初,XPath被设计为XSLT和XPointer的语言。 XPath 1.0在1999年成为W3C标准。较新的XPath 2.0在2007年获得规范状态。
随着其他XML规范的出现,XPath的使用也出现了。 如今,XPath已成为在XML模式,ISO Schematron,XQuery和XForms中导航XML的首选语言。 具有讽刺意味的是,但有充分的理由,XPath不是基于XML语法的。 它使用自己的语法来避免与URI和其他XML相关语法的冲突。
在PHP中使用XPath时,请记住不要单独使用XPath。 您可以使用它作为在其他XML规范之一中工作时在内存中浏览XML的工具。
出于本文的目的,我在讨论和示例中使用了更广泛使用的XPath 1.0规范。 XPath 2.0向后兼容XPath 1.0,但是PHP今天对XPath 2.0的支持有限。
XPath规范提供了其标准用法和术语的详细说明。 如果您期望将XPath与PHP一起复杂使用,则此规范是可靠的参考点。 否则,XPath规范可以归纳为四个主要的关注领域,如表1所示 。
区 | 描述 | 例子 |
---|---|---|
位置路径 | 包含位置步骤,轴,谓词和缩写语法。 | 父::节点,子::文本(),属性:: *,/ PRODUCTS / PRODUCT [3] / NAME |
资料模型 | 将XML描述为树。 包含根,属性,文本,名称空间,元素,处理指令和注释的节点。 | /,/ ns1:PRODUCTS / ns1:PRODUCT,@category |
表达方式 | 可能包含变量引用,函数,布尔值,数字,字符串和谓词。 | / PRODUCTS / PRODUCT / NAME [字符串长度()> 15] /../@ category |
功能 | XPath 1.0具有27个内置函数,这些函数分为节点集,字符串,布尔值或数字函数。 | string-length(),true(),sum() |
在编写PHP代码之前,花一些时间检查XPath节点,路径和功能。 清单1中的products.xml文件提供了一些常用表达式的示例,这些表达式可基于谓词在XML路径中定位数据,定位节点的原子值并利用函数。
<?xml version="1.0" encoding="UTF-8"?>
<PRODUCTS>
<PRODUCT category="software">
<SKU>soft32323</SKU>
<SUB_CATEGORY>Business Analysis</SUB_CATEGORY>
<NAME>Widget Reporting</NAME>
<PRICE>4500</PRICE>
</PRODUCT>
<PRODUCT category="software">
<SKU>soft32323</SKU>
<SUB_CATEGORY>Business Analysis</SUB_CATEGORY>
<NAME>Pro Reporting</NAME>
<PRICE>2300</PRICE>
</PRODUCT>
<PRODUCT category="storage">
<SKU>soft32323</SKU>
<SUB_CATEGORY>Tape Systems</SUB_CATEGORY>
<NAME>Tapes Abound</NAME>
<PRICE>2300</PRICE>
</PRODUCT>
<PRODUCT category="storage">
<SKU>soft32323</SKU>
<SUB_CATEGORY>Disk Systems</SUB_CATEGORY>
<NAME>Widget100 Series</NAME>
<PRICE>6500</PRICE>
</PRODUCT>
</PRODUCTS>
/PRODUCTS
返回作为PRODUCTS
节点的子级的所有节点,其中有四个。 注意正斜杠( /
)符号。 如果您熟悉基于UNIX的操作系统,则知道斜杠代表绝对路径。 就像在UNIX文件路径中一样,当不确定当前上下文位置时,可以使用绝对路径。 对于清单1中的文档, PRODUCTS
是根节点。
相对路径也可以与XPath一起使用。 在表达式中使用..
时,它会指示表达式从层次结构中的当前节点开始向上处理一级(再次类似于在UNIX操作系统中使用目录)。 例如, ../PRODUCT/SKU
PRODUCT
SKU返回与每个PRODUCT
节点关联的所有四个SKU编号的原子节点值。
选择属性节点需要在XPath中使用特殊语法。 如果要返回软件类别中列出的所有PRODUCT
节点,则表达式/PRODUCTS/PRODUCT[@category='software']
执行此操作。 在此表达式中, category
被视为XML文档中的属性。 XPath可以选择带有符号(@)的属性。 或者,您可以使用attribute::
语法选择一个属性,使得表达式为/PRODUCTS/PRODUCT[attribute::category='software']
。 大多数人发现at符号不太冗长,更易于使用。
要为价格超过$ 2,500的产品选择所有产品名称的原子节点值(即实际文本值),可以将表达式编写为/PRODUCTS/PRODUCT[PRICE > 2500]/NAME
。 执行时,此表达式返回产品名称Widget Reporting
和Widget100 Series
。
在将XPath与PHP结合使用之前,请看一个最终表达式示例: /PRODUCTS/PRODUCT/NAME[string-length( ) > 15]/../@category
。 执行时,此表达式返回两个值: software
和storage
。 具体来说,此表达式匹配名称长度超过15个字符的每个产品的类别值。
清单1中的XML文档是本文演示的XPath表达式的源文档。
PHP支持XML和XPath应该不足为奇。 实际上,最流行的Web脚本语言在其核心库中提供了一些使用XPath的良好功能。
在核心PHP库中,使用XML时,您有几种选择:
SimpleXML易于使用,并且适用于相对简单的XML相关杂务。 它确实有一些局限性。 例如,它不完全支持验证,编写和名称空间。 如果要处理大型XML数据树,请记住,SimpleXML在处理之前将完整的XML文档树加载到内存中。
如果需要执行更复杂的XPath表达式并需要完全控制文档,则可以选择DOM。 DOM是文档对象模型的缩写,它是W3C标准。 您可以通过将PHP作为扩展安装来启用DOM。 诸如DOM之类的扩展通常很容易安装和启用。 很多时候,这只是在php.ini文件中取消注释一行以启用已编译模块的情况。 与SimpleXML一样,DOM在处理之前会将完整的XML文档树加载到内存中。 正如您将在本文后面看到的那样,DOMXPath也非常令人愉快。
您还可以从PHP扩展和应用程序存储库(PEAR)存储库下载并安装XML_XPath
。 此类使用DOM,并提供了一种使用XPath进行查询以进行文档处理和提取原子节点值的方法。
如果使用Zend Framework,则可以使用Zend_Dom_Query
库。 如果您的特定PHP框架没有为XML和XPath提供特殊的类或函数,则可以简单地使用PHP已经提供的功能。
没有SimpleXML或DOMXPath的帮助,XMLWriter / Reader不会直接支持XPath,因此本文将不再赘述。
无论使用哪种库或框架,了解如何创建XPath表达式都是获得全部潜能的关键。 将XPath与PHP XML相关的库一起使用时,XPath语法是相同的。 以下示例和演示结合使用DOM和SimpleXML。
使用清单1中的示例products.xml文件和PHP5 SimpleXML API,您可以尝试各种XPath表达式。
当您执行清单2中的代码时,结果当然是将完整的XML文件转储为数组。 XPath表达式/PRODUCTS
导致作为根节点( PRODUCTS
)的每个子节点的匹配。
<?php
$xml = simplexml_load_file("products.xml");
$products = $xml->xpath("/PRODUCTS");
print_r($products);
?>
------------------------------------------------------------
OUTPUT:
Array ( [0] => SimpleXMLElement Object ( [PRODUCT] =>
Array ( [0] => SimpleXMLElement Object
( [@attributes] => Array ( [category] => software ) [SKU] =>
soft1234 [SUB_CATEGORY] =>
Business Analysis [NAME] => Widget Reporting [PRICE] => 4500 ) [1] =>
SimpleXMLElement Object
( [@attributes] => Array ( [category] => software ) [SKU] => soft5678
[SUB_CATEGORY] =>
Business Analysis [NAME] => Pro Reporting [PRICE] => 2300 ) [2] =>
SimpleXMLElement Object
( [@attributes] => Array ( [category] => storage ) [SKU] =>
stor01010 [SUB_CATEGORY] => Tape Systems [NAME] =>
Tapes Abound [PRICE] => 1900 )
[3] => SimpleXMLElement Object ( [@attributes] =>
Array ( [category] => storage ) [SKU] =>
stor23232 [SUB_CATEGORY] => Disk Systems [NAME] =>
Widget100 Series [PRICE] => 6500 ) ) ) )
当执行清单3中的代码时,结果是XML树的每个NAME
节点的值的数组输出。 请注意,表达式/PRODUCTS/PRODUCT/NAME
如何在XML树中找到它匹配的每个节点的,而不是仅第一个或最后一个。
<?php
$xml = simplexml_load_file("products.xml");
$products = $xml->xpath("/PRODUCTS/PRODUCT/NAME");
print_r($products);
?>
------------------------------------------------------------
OUTPUT:
Array ( [0] => SimpleXMLElement Object ( [0] => Widget Reporting )
[1] => SimpleXMLElement Object ( [0] => Pro Reporting ) [2] =>
SimpleXMLElement Object ( [0] => Tapes Abound ) [3] =>
SimpleXMLElement Object ( [0] => Widget100 Series ) )
如果您需要根据某些条件来确定一个或多个特定节点的值,请遵循清单4和5中的示例。
定位原子节点值是从XML文档中提取所需的值。 当您执行清单4中的代码时,结果是一个节点的原子值。
<?php
$xml = simplexml_load_file("products.xml");
$products = $xml->xpath("/PRODUCTS/PRODUCT[SKU='soft5678']/NAME");
print_r($products);
?>
------------------------------------------------------------
OUTPUT:
Array ( [0] => SimpleXMLElement Object ( [0] => Pro Reporting ) )
XPath表达式/PRODUCTS/PRODUCT[SKU='soft5678']/NAME
指定与该表达式匹配的所有节点。 在这种情况下,只有一种产品的SKU编号匹配。 如果需要定位节点的值,因为它与它在XML树中的位置有关 ,则可以使用position()
函数。
您可以在XPath中使用条件表达式来进一步查明特定节点的位置。 清单5显示了一个使用带有条件表达式的SimpleXML和XPath的示例。
<?php
$xml = simplexml_load_file("products.xml");
$products = $xml->xpath("/PRODUCTS/PRODUCT[@category='software' and PRICE > 2500]");
print_r($products);
?>
------------------------------------------------------------
OUTPUT:
Array ( [0] => SimpleXMLElement Object ( [@attributes] =>
Array ( [category] => software )
[SKU] => soft1234 [SUB_CATEGORY] => Business Analysis [NAME] =>
Widget Reporting [PRICE] => 4500 ) )
您可能已经注意到,清单2 , 3 , 4 ,和5有相同PHP代码,唯一的区别是XPath表达式。 当您使用SimpleXML掌握这些步骤时,您将拥有XPath语言的全部功能。 使用SimpleXML时,PHP代码采取的步骤总结如下:
Object->xpath class.
编写并执行XPath表达式Object->xpath class.
每个清单中的输出结果是print_r($products);
声明。 它转储值以显示为数组。 实际上,您很可能会得到结果并使用PHP对它执行一些操作。
清单6使用DOM和DOMXPath来处理XML和XPath。
<?php
$doc = new DOMDocument;
$doc->load('products.xml');
$xpath = new DOMXPath($doc);
$products = $xpath->query("/PRODUCTS/PRODUCT[SKU='soft5678']/NAME");
foreach ($products as $product)
{
print($product->nodeValue);
}
?>
------------------------------------------------------------
OUTPUT:
Pro Reporting
用于DOM和DOMXPathPHP代码序列并不比SimpleXML步骤复杂得多。 清单6中的步骤按以下顺序总结:
同样,当您对使用DOMPHP代码片段感到满意时,可以使用XPath来完成繁琐的工作。
实际上,您可以在不使用XSLT的情况下将XML转换为XHTML。 您可以仅使用SimpleXML或DOM扩展前面的示例并变得更有创意,并创建XHTML文件进行显示。 您可能会对这种方法更满意。 但是,考虑到XPath大量用于XSLT转换,而PHP确实支持XSLT,则适合进行演示。 此外,使用XSLT可以节省大量时间和挫败感!
在将XML数据转换为其他格式(例如使用XSLTHTML)时,必须对XPath有扎实的了解。
RSS和Atom提要基于XML,因此XPath是横切提要和选择所需数据的理想工具。 假设本文具有针对各种PHP和XPath技术的自己的Atom提要,则可以使用一个PHP XML库从提要中提取条目,并根据需要在网站上显示它们。
与清单7中的文件一样简单的XSLT文件在很大程度上取决于XPath。
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<xsl:template match="/">
<html>
<head><title><xsl:value-of select="//atom:title"/></title></head>
<table>
<tr><td><xsl:value-of select="//atom:title"/></td></tr>
<tr><td><i>"<xsl:value-of select="//atom:subtitle" />",</i></td></tr>
<tr><td>by <xsl:value-of select="//atom:author"/></td></tr>
<xsl:for-each select="//atom:feed/entry">
<table border="1" >
<tr>
<td>Title</td><td><xsl:value-of select="//atom:title"/></td>
</tr>
<tr>
<td>Summary</td><td><xsl:value-of select="//atom:summary"/></td>
</tr>
<tr>
</tr>
</table><br/>
</xsl:for-each>
</table>
</html>
</xsl:template>
</xsl:stylesheet>
两个正斜杠( //
)指示XPath匹配从根节点开始的第一个命名节点。 标题,字幕和作者各只有一个节点,这是一种无需输入绝对路径即可表达位置路径的快捷方式。 因为for-each
循环在//feed/entry
节点的上下文中起作用,所以使用标题和摘要的相对路径。
现在,使用清单7中的XSLT文件,可以编写适当PHP代码来执行转换,如清单8所示 。
<?php
$doc = new DOMDocument();
$xmlStream = <<<MyFeed
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title>Using XPath with PHP</title>
<author><name>Tracy Bost</name></author>
<subtitle type="html">
Let XPath do the hard work for you when working with XML</subtitle>
<link rel="self" type="text/html"
hreflang="en" href="http://www.ibm.com/developerworks/"/>
<updated>15 Aug 2011 22:51:48 +0000</updated>
<entry>
<title>SimpleXML & XPath </title>
<summary>If you are using SimpleXML to parse XML or
RSS feeds, XPath is great to use!</summary>
<link rel="self" type="text/html" hreflang="en" href=""/>
<published>21 Apr 2011 04:00:00 +0000</published>
<updated>21 Apr 2011 04:00:00 +0000</updated>
</entry>
<entry>
<title>DOMXPath</title>
<summary>If you are using DOM for traversal XML documents,
give DOMXPath a try! </summary>
<link rel="self" type="text/html" hreflang="en" href=""/>
<id>tag:developerWorks.dw,19 Apr 2011 04:00:00 +0000</id>
<published>12 Aug 2011 04:00:00 +0000</published>
<updated>12 Aug 2011 04:00:00 +0000</updated>
</entry>
<entry>
<title>XMLReader with XPath</title>
<summary>For complex XML document reading and writing,
using XPath with XReader can ease your burden!</summary>
<link rel="self" type="text/html" hreflang="en" href=""/>
<id>tag:developerWorks.dw,19 Apr 2011 04:00:00 +0000</id>
<published>08 Aug 2011 04:00:00 +0000</published>
<updated>08 Aug 2011 04:00:00 +0000</updated>
</entry>
</feed>
MyFeed;
$doc->loadXML($xmlStream);
$xpath = new DOMXpath($doc);
$xslt = new XSLTProcessor();
$xsl = new DOMDocument();
$xsl->load( 'xsl/article_feed.xsl', LIBXML_NOCDATA);
$xslt->importStylesheet( $XSL );
print $xslt->transformToXML( $doc );
?>
------------------------------------------------------------
OUTPUT:
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Using XPath with PHP</title></head><body><table><tr>
<td>Using XPath with PHP</td></tr><tr>
<td><i>"Let XPath do the hard work for you when working with XML",</i></td>
</tr><tr><td>by Tracy Bost
</td></tr><table border="1"><tr><td>Title</td>
<td>SimpleXML & XPath </td></tr>
<tr><td>Summary</td>
<td>If you are using SimpleXML to parse XML or RSS feeds,
XPath is great to use!</td>
</tr><tr/></table>
<br/>
<table border="1">
<tr><td>Title</td>
<td>DOMXPath</td>
</tr>
<tr><td>Summary</td>
<td>If you are using DOM for traversal XML documents,
give DOMXPath a try! </td>
</tr><tr/></table><br/>
<table border="1">
<tr><td>Title</td><td>XMLReader with XPath</td>
</tr>
<tr><td>Summary</td>
<td>For complex XML document reading and writing,
using XPath with XReader can ease your burden!</td>
</tr><tr/></table><br/>
</table>
</body>
</html>
请注意, 清单8没有$xpath->query()
语句,如清单6所示 。 所有XPath表达式都位于XSL文件中。 只需使用DOM导入样式表,然后让它执行转换即可!
在本文中,向您介绍了XPath,以及在使用XML时如何在PHP5环境中使用它。 像PHP中提供的许多其他库一样,XML库使您作为开发人员可以专注于功能需求,而不是类和对象的低级连接。 XPath可以帮助消除在XML中定位和解析数据的繁琐任务。 根据您的需求,您可以选择使用SimpleXML,DOM或诸如Zend Framework之类的框架的XML库。 幸运的是,它们都以标准方式与W3C XPath一起使用。 因此,当您加载下一个XML文件或数据流时,不必担心导航到需要处理的确切值。
翻译自: https://www.ibm.com/developerworks/opensource/library/x-xpathphp/index.html
php 使用xpath