使用Nokogiri解析带有xhtml:link标记的HTML?

使用Nokogiri解析带有xhtml:link标记的HTML?,html,ruby,xpath,nokogiri,Html,Ruby,Xpath,Nokogiri,我正在使用Nokogiri gem解析HTML数据 $ gem list nokogiri *** LOCAL GEMS *** nokogiri (1.6.2.1) 示例HTML是: <html> <body> <xhtml:link> <div> Some content. </div> </xhtml:link> </body> </htm

我正在使用Nokogiri gem解析HTML数据

$ gem list nokogiri

*** LOCAL GEMS ***

nokogiri (1.6.2.1)
示例HTML是:

<html>
  <body>
    <xhtml:link>
      <div>
    Some content.
      </div>
    </xhtml:link>
  </body>
</html>

一些内容。
我越来越

>>  doc.xpath('/html/body/xhtml:link/div')
Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: /html/body/xhtml:link/div
    from /var/lib/gems/1.9.1/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node.rb:159:in `evaluate'
    from /var/lib/gems/1.9.1/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node.rb:159:in `block in xpath'
    from /var/lib/gems/1.9.1/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node.rb:150:in `map'
    from /var/lib/gems/1.9.1/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node.rb:150:in `xpath'
    from (irb):95
    from /usr/bin/irb:12:in `<main>'
>doc.xpath('/html/body/xhtml:link/div')
Nokogiri::XML::XPath::SyntaxError:未定义的命名空间前缀:/html/body/xhtml:link/div
from/var/lib/gems/1.9.1/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node.rb:159:in“evaluate”
from/var/lib/gems/1.9.1/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node.rb:159:in`block in xpath'
from/var/lib/gems/1.9.1/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node.rb:150:在“地图”中
from/var/lib/gems/1.9.1/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node.rb:150:in'xpath'
起始(irb):95
from/usr/bin/irb:12:in`'
可以找到完整的示例live HTML页面


如何避免此错误?

您需要将XML名称空间(
xhtml
在您的示例中)添加到根元素中,以便Nokogiri能够识别它,除非您这样做,否则Nokogiri将忽略它并显示错误

您可以这样做:

<html xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <body>
        <xhtml:link>
            <div>Some content.</div>
        </xhtml:link>
    </body>
</html>
另一种方法是手动将该命名空间添加到根文档:

doc.root.add_namespace 'xhtml', 'http://www.w3.org/1999/xhtml'
doc.xpath('/html/body/xhtml:link/div')
虽然这两种方法都会消除错误,但这两种情况下的查询都只会为我返回一个空数组,这与文档中最初包含
xmlns
属性时的情况不同。

如果您确定同一上下文中没有同名的非固定元素,则可以忽略名称空间。名称空间影响元素和属性名称。如果使用
node()
*
选择它们,则可以在谓词中测试
local-name()
,而无需处理名称空间

在您的示例中,您可以选择
xhtml:link
元素,方法是选择
body
上下文中的所有元素,然后将结果集限制为只有本地名称等于
link
的元素:

doc.xpath('/html/body/*[local-name()="link"]/div')

如果在主体中出现不需要的HTML
元素(它们不应该存在,但HTML解析器不在乎它们是否存在),则可能会选择它们。但如果它们出现,它们应该是空元素。不会有一个内部有
的,所以你是安全的。

不是真正的问题,但似乎你没有关闭
主体
标记。你不能
doc.xpath('/html/body/link/div')
它吗?我通过检查Firebug中的元素来获得xpath。这适用于其他文档,但每当元素标记中有冒号“:”时,就会出现上述错误。您是将其解析为HTML还是XML?如果您解析为HTML,那么Nokogiri会剥离名称空间,因此您可以只使用
link
。我无法修改现有HTML,因为它来自外部源。那么,我可以向Nokigiri提供名称空间,以便它可以在不修改HTML内容的情况下解析吗?您可以使用轻松删除名称空间。
doc.xpath('/html/body/*[local-name()="link"]/div')