2009-11-15 63 views
23

我正在使用Nokogiri :: XML来解析来自Amazon SimpleDB的响应。响应是一样的东西:为什么Nokogiri xpath不像xmlns声明

<SelectResponse xmlns="http://sdb.amazonaws.com/doc/2007-11-07/"> 
    <SelectResult> 
    <Item> 
     <Attribute><Name>Foo</Name><Value>42</Value></Attribute> 
     <Attribute><Name>Bar</Name><Value>XYZ</Value></Attribute> 
    </Item> 
    </SelectResult> 
</SelectResponse> 

如果我刚刚到手的响应直接到引入nokogiri,所有的XPath查询(例如doc/"//Item/Attribute[Name='Foo']/Value")返回一个空数组。但是,如果我从SelectResponse标记中删除xmlns属性,则它完美地起作用。

是否有一些额外的事情我需要做的帐户名称空间声明?这种解决方法非常像黑客攻击。

回答

32

XPath查询查找不在任何名称空间中的元素。你需要告诉你的XPath处理器,你正在寻找在命名空间中的元素做,与引入nokogiri是这个http://sdb.amazonaws.com/doc/2007-11-07/

方式一:

doc = Nokogiri::XML.parse(...) 
doc.xpath("//aws:Item/aws:Attribute[Name='Foo']/aws:Value", {"aws" => "http://sdb.amazonaws.com/doc/2007-11-07/"}) 
+0

这是固定的。谢谢。 – 2009-11-15 15:45:08

+8

只需提供像“doc.xpath('// xmlns:Item ...”这样的“** xmlns:**”即可。 – user569825 2013-03-19 14:49:40

20

我发现这确实有助于理解这是怎么回事: http://tenderlovemaking.com/2009/04/23/namespaces-in-xml.html

基本上,如果您有一个定义的名称空间(通过xmlns=),则必须在xpath搜索中使用名称空间。所以你的情况

,你可以做的三两件事之一:

  • 删除的xmlns从根SearchResponse属性。在这种情况下,您的原始的无命名空间xpath查询将会起作用。
  • 使用默认的命名空间中的XPath查询doc/"//xmlns:Item/xmlns:Attribute[xmlns:Name='Foo']/xmlns:Value"
  • xpath方法调用的第二个参数定义自定义命名空间和使用,在您的查询,如图hrnt的解决方案上面
+4

有一个'remove_namespaces!'方法[http:// nokogiri .org/Nokogiri/XML/Document.html#method-i-remove_namespaces%21)。 – RobinGower 2011-10-04 22:17:45

+1

@RobinGower是的,它说'有关为什么这可能不是一件好事情的更多信息,请将浏览器指向' [tenderlovemaking.com/2009/04/23/namespaces-in-xml/](http://tenderlovemaking.com/2009/04/23/namespaces-in-xml) – nurettin 2012-07-16 12:14:54

+0

评论中的两个链接都已过时。 [remove_namespaces!]的更新文档链接(http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Document:remove_namespaces!) – Jason 2015-07-29 17:38:06