是否需要在XPATH中使用的XHTML文档的命名空间

时间:2011-05-30 17:28:41

标签: php html xhtml xpath xml-namespaces

我正在为网页的某些特定部分抓取一些网页。我使用phpcurlxpath来获取页面的部分。但是人们建议我应该使用namespaces XHTML文档来XPATHs工作。据我所知namespaces用于避免各种元素名称之间的冲突,为什么在这种情况下我需要namespaces?我实际上是使用Tidy将网页转换为XHTML。我是否真的需要命名空间,如果是,在哪种情况下是因为相同的代码without namespaces适用于从wikipedia抓取内容。即使修改我的PHP代码以包含namespaces后,代码也无法用于某些网址。你可以看看这个post

2 个答案:

答案 0 :(得分:3)

首先:命名空间是XML中的基本概念。如果您不熟悉命名空间,请花些时间学习和理解它们。

当且仅当您正在处理的XML文档使用名称空间时,您需要在XPath表达式中使用名称空间前缀。

所有XPath(1.0)名称测试都使用限定名称,即没有名称空间前缀的表达式始终只与无名称空间中的目标匹配。这意味着表达式/element-1/element-2总是在搜索没有命名空间定义的元素(换句话说:它们属于无命名空间,换句话说:它们具有空命名空间URI)。示例XPath表达式适用于此文档...

<element-1>
    <element-2>Works!</element-2>
</element-1>

...但它不适用于此文件...

<ns:element-1 xmlns:ns="http://example.com">
    <ns:element-2>Doesn't work</ns:element-2>
</ns:element-1>

...因为在这种情况下<element-1><element-2>都属于命名空间(URI http://example.com)。另请注意,如果文档具有默认命名空间,则元素可能属于命名空间,即使它们没有任何命名空间前缀。这份文件......

<element-1 xmlns="http://example.com">
    <element-2>Similar to previous, and doesn't work either.</element-2>
</element-1>

...与第二个文档示例相同,并且在其上使用XPath也需要使用名称空间前缀。

从此文档中搜索数据需要使用一些前缀注册名称空间URI,然后在XPath表达式中使用该前缀。像/px:element-1/px:element-2这样的东西。请注意,您注册的前缀不需要与文档中使用的前缀匹配,但URI必须完全匹配。另一点需要注意的是,即使默认命名空间中的元素没有前缀,您仍然需要使用在XPath表达式中定义的前缀来匹配它们。

因此,XPath查询中对名称空间前缀的需求取决于文档。一些网站将其页面作为有效的XHTML文档提供,因此所有元素都属于XHTML命名空间。其他一些网站提供没有命名空间的HTML或XHTML,这在技术上是无效的XHTML。

命名空间前缀的注册方式取决于您使用的XML框架或库。在php和SimpleXML中,这大致就是这样做的

$your_xml_doc->registerXPathNamespace("ns", "http://example.com");
$result = $your_xml_doc->xpath('/ns:element-1/ns:element-2');

答案 1 :(得分:1)

可以 使用不使用名称空间的XPath表达式。

如果您正在抓取Web内容并且不确定它是XHTML还是未绑定到命名空间的格式良好的HTML,那么您可能会发现为XPath使用更通用的匹配条件会更方便忽略元素的命名空间。

您可以通过任何元素的通用匹配(例如*)来执行此操作,然后对元素的local-name()使用谓词过滤器(例如*[local-name()='table'])。

这样做将匹配具有该名称的任何元素,无论它是否绑定到特定命名空间。

例如:

//*[local-name()='body']/*[local-name()='table'][4]
     /*[local-name()='tbody']/*[local-name()='tr'][3]
     /*[local-name()='td'][4]