首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Ruby的Nokogiri解析XML文档时出错

用Ruby的Nokogiri解析XML文档时出错
EN

Stack Overflow用户
提问于 2021-01-29 12:00:33
回答 2查看 236关注 0票数 0

使用Ruby的Nokogiri库,我希望解析一个XML文档如下,从中提取一些元素(如"tsn“或”王国“):

代码语言:javascript
复制
<ns:searchByScientificNameResponse xmlns:ns="http://itis_service.itis.usgs.gov">
<ns:return xmlns:ax21="http://data.itis_service.itis.usgs.gov/xsd" xmlns:ax23="http://metadata.itis_service.itis.usgs.gov/xsd" xmlns:ax26="http://itis_service.itis.usgs.gov/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax21:SvcScientificNameList">
<ax21:scientificNames xsi:type="ax21:SvcScientificName">
<ax21:tsn>26339</ax21:tsn>
<ax21:author>L.</ax21:author>
<ax21:combinedName>Vicia faba</ax21:combinedName>
<ax21:kingdom>Plantae</ax21:kingdom>
<ax21:unitInd1 xsi:nil="true" />
<ax21:unitInd2 xsi:nil="true" />
<ax21:unitInd3 xsi:nil="true" />
<ax21:unitInd4 xsi:nil="true" />
<ax21:unitName1>Vicia</ax21:unitName1>
<ax21:unitName2>faba</ax21:unitName2>
<ax21:unitName3 xsi:nil="true" />
<ax21:unitName4 xsi:nil="true" />
</ax21:scientificNames>
</ns:return>
</ns:searchByScientificNameResponse>

打开文档后,使用

代码语言:javascript
复制
doc = Nokogiri::XML(File.open("sample.xml"))

如果我用

代码语言:javascript
复制
tsn = doc.at_xpath("//tsn")
puts tsn

我得到一个零值,如果我使用

代码语言:javascript
复制
tsn = doc.at_xpath("//:tsn")

我得到一个错误: Nokogiri::XML::XPath::SyntaxError (错误:无效表达式: //:tsn)

有人能帮我个忙吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-29 20:04:04

因此,问题在于XML包含名称空间。

有两种选择:

  1. 删除名称空间
代码语言:javascript
复制
doc.remove_namespaces! 
doc.at_xpath("//tsn") 
#=> #<Nokogiri::XML::Element:0x2add795ea3b8 name="tsn" children=[#<Nokogiri::XML::Text:0x2add795e5f70 "26339">]>
  1. 引用命名空间:
代码语言:javascript
复制
doc.at_xpath("//ax21:tsn", 'ax21' => "http://data.itis_service.itis.usgs.gov/xsd") 
#=> #<Nokogiri::XML::Element:0x2add795ea3b8 name="tsn" children=[#<Nokogiri::XML::Text:0x2add795e5f70 "26339">]>

根据注释,您似乎只对该节点的文本感兴趣。您可以通过多种方式检索:

代码语言:javascript
复制
doc.at_xpath("//tsn").text()
#=> "26339"
doc.at_xpath("//tsn/text()").to_s
#=> "26339"
# If you want tsn and kingdom at the same time 
doc.xpath('//tsn/text() | //kingdom/text()').map(&:to_s)
#=> ["26339", "Plantae"]

示例

票数 1
EN

Stack Overflow用户

发布于 2021-01-29 15:24:16

这是我想出来的

代码语言:javascript
复制
require 'nokogiri'

doc = Nokogiri::XML(File.open("sample.xml"))

node_names = []
doc.xpath('//*').each do |node|
    node_names << node.name
end

print node_names
#=>["ns:searchByScientificNameResponse", "ns:return", "ax21:scientificNames", "ax21:tsn", "ax21:author", "ax21:combinedName", "ax21:kingdom", "ax21:unitInd1", "ax21:unitInd2", "ax21:unitInd3", "ax21:unitInd4", "ax21:unitName1", "ax21:unitName2", "ax21:unitName3", "ax21:unitName4"]


node_names.each do |elem|
  if elem == "ax21:kingdom"
    puts elem
  elsif
    elem == ("ax21:tsn")
    puts elem
  end
end
#=>ax21:tsn
#=>ax21:kingdom

不确定这是否是您想要的,所以我将提供给我这个解决方案的文档链接:https://gist.github.com/carolineartz/10276637

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65954070

复制
相关文章

相似问题

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