首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在XPATH中使用XHTML文档的名称空间是必需的吗

问在XPATH中使用XHTML文档的名称空间是必需的吗
EN

Stack Overflow用户
提问于 2011-05-31 01:28:41
回答 2查看 216关注 0票数 0

我正在抓取一些网页的一些特定部分的网页。我使用php,curl和xpath来获取页面的一部分。但是人们建议我应该使用XHTML文档的namespaces才能使XPATHs工作。据我所知,namespaces是用来避免各种元素名称之间的冲突的,那么在这种情况下我为什么需要namespaces呢?实际上,我正在使用Tidy将网页转换为XHTML。我真的需要名称空间吗?如果需要,在哪种情况下需要,因为在从wikipedia中抓取内容时,相同的代码without namespaces工作得很好。此外,即使在修改我的php代码以包含namespaces之后,该代码也不适用于某些urls。你可以看看这个post。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-05-31 03:00:49

首先:命名空间是XML语言中的一个基本概念。如果你不熟悉命名空间,请花点时间来学习和理解它们。

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

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

代码语言:javascript
复制
<element-1>
    <element-2>Works!</element-2>
</element-1>

...but它在此文档上不起作用...

代码语言:javascript
复制
<ns:element-1 xmlns:ns="http://example.com">
    <ns:element-2>Doesn't work</ns:element-2>
</ns:element-1>

...because在本例中,<element-1>和<element-2>都属于一个名称空间(使用URI http://example.com)。还要注意,如果文档有一个默认的名称空间,那么元素可能属于一个名称空间,即使它们没有任何名称空间前缀。这份文件...

代码语言:javascript
复制
<element-1 xmlns="http://example.com">
    <element-2>Similar to previous, and doesn't work either.</element-2>
</element-1>

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

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

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

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

代码语言:javascript
复制
$your_xml_doc->registerXPathNamespace("ns", "http://example.com");
$result = $your_xml_doc->xpath('/ns:element-1/ns:element-2');
票数 3
EN

Stack Overflow用户

发布于 2011-05-31 19:20:24

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

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

您可以通过对任何元素(例如*)进行泛型匹配来实现这一点,然后对元素的local-name() (例如*[local-name()='table'])使用谓词过滤器。

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

例如:

代码语言:javascript
复制
//*[local-name()='body']/*[local-name()='table'][4]
     /*[local-name()='tbody']/*[local-name()='tr'][3]
     /*[local-name()='td'][4]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6179152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档