且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在带有前缀但没有名称空间的节点上使用xpath?

更新时间:2023-09-12 14:06:58

问题是XML文档中未正确定义名称空间.结果,Nokogiri认为节点名称是"a:root",而不是"a"是名称空间,而"root"是节点名称:

The problem is that the namespace is not properly defined in the XML document. As a result, Nokogiri sees the node names as being "a:root" instead of "a" being a namespace and "root" being the node name:

xml = %Q{
    <?xml version="1.0" encoding="UTF-8"?>
    <a:root>
      <a:thing>stuff0</a:thing>
      <a:thing>stuff1</a:thing>
    </a:root>
}
doc = Nokogiri::XML(xml)
puts doc.at_xpath('*').node_name
#=> "a:root"
puts doc.at_xpath('*').namespace
#=> ""

解决方案1-用冒号指定节点名称

一种解决方案是搜索名称为"a:thing"的节点.您无法执行//a:thing,因为XPath会将"a"视为命名空间.您可以通过执行//*[name()="a:thing"]来解决此问题:

One solution is to search for nodes with the name "a:thing". You cannot do //a:thing since the XPath will treat the "a" as a namespace. You can get around this by doing //*[name()="a:thing"]:

xml = %Q{
    <?xml version="1.0" encoding="UTF-8"?>
    <a:root>
      <a:thing>stuff0</a:thing>
      <a:thing>stuff1</a:thing>
    </a:root>
}
doc = Nokogiri::XML(xml)
things = doc.xpath('//*[name()="a:thing"]')
puts things
#=> <a:thing>stuff0</a:thing>
#=> <a:thing>stuff1</a:thing>

解决方案2-修改XML文档以定义名称空间

另一种解决方案是修改XML文件,以正确定义名称空间.然后,文档将按预期使用命名空间:

An alternative solution is to modify the XML file that you get to properly define the namespace. The document will then behave with namespaces as expected:

xml = %Q{
    <?xml version="1.0" encoding="UTF-8"?>
    <a:root>
      <a:thing>stuff0</a:thing>
      <a:thing>stuff1</a:thing>
    </a:root>
}
xml.gsub!('<a:root>', '<a:root xmlns:a="foo">')
doc = Nokogiri::XML(xml)
things = doc.xpath('//a:thing')
puts things
#=> <a:thing>stuff0</a:thing>
#=> <a:thing>stuff1</a:thing>