ruby - 如何在有前缀但没有 namespace 的节点上使用 xpath?

标签 ruby xml xpath namespaces nokogiri

我有一个 XML 文件需要解析。我无法控制文件的格式,也无法更改它。

该文件使用了一个前缀(称之为a),但它并未在任何地方为该前缀定义 namespace 。我似乎无法使用 xpath 来查询具有 a 命名空间的节点。

这是xml文件的内容

<?xml version="1.0" encoding="UTF-8"?>

<a:root>
  <a:thing>stuff0</a:thing>
  <a:thing>stuff1</a:thing>
  <a:thing>stuff2</a:thing>
  <a:thing>stuff3</a:thing>
  <a:thing>stuff4</a:thing>
  <a:thing>stuff5</a:thing>
  <a:thing>stuff6</a:thing>
  <a:thing>stuff7</a:thing>
  <a:thing>stuff8</a:thing>
  <a:thing>stuff9</a:thing>
</a:root>

我正在使用 Nokogiri 查询文档:

doc = Nokogiri::XML(open('text.xml'))
things = doc.xpath('//a:thing')

失败并给出以下错误:

Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: //a:thing

根据我的研究,我发现我可以在 xpath 方法中为前缀指定 namespace :

things = doc.xpath('//a:thing', a: 'nobody knows')

这将返回一个空数组。

获取所需节点的最佳方式是什么?

最佳答案

问题是命名空间没有在 XML 文档中正确定义。因此,Nokogiri 将节点名称视为“a:root”,而不是将“a”视为 namespace ,将“root”视为节点名称:

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”视为 namespace 。您可以通过执行 //*[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 文件以正确定义命名空间。然后文档将按预期使用命名空间:

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>

关于ruby - 如何在有前缀但没有 namespace 的节点上使用 xpath?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20004081/

相关文章:

mysql - 在mac上安装mysql2时出现"Failed to build gem native extension"错误

ruby - Datamapper "Update"不更新记录

xml - 有没有办法在应用程序设置中使用字典或 xml?

java - 使用 StAX 和 XPath 读取巨大的 XML 文件

xml - xpath/xslt相等检查多个值

xml - Xpath 使用谓词在数据中匹配带有斜线的节点

ios - FaSTLane ‘./metadata’ : ar-SA 中的屏幕截图/元数据不支持的目录名称

ruby-on-rails - rails 3输出冲洗

不合格属性名称的 XML 默认命名空间?

xpath - Sublime Text - XPath 插件快捷方式