【问题标题】:Error parsing XML document with Ruby's Nokogiri使用 Ruby 的 Nokogiri 解析 XML 文档时出错
【发布时间】:2021-05-03 08:22:45
【问题描述】:

使用 Ruby 的 Nokogiri 库,我想按如下方式解析 XML 文档,从中提取一些元素(如“tsn”或“kingdom”):

<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>

打开文档后用

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

如果我使用

tsn = doc.at_xpath("//tsn")
puts tsn

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

tsn = doc.at_xpath("//:tsn")

我得到一个错误:Nokogiri::XML::XPath::SyntaxError (ERROR: Invalid expression: //:tsn)

有人可以帮我吗?

【问题讨论】:

    标签: ruby nokogiri


    【解决方案1】:

    这是我想出来的

    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

    【讨论】:

    • 感谢您的回答,但我想要的是属性 ax21:tsn 的值,在本例中为整数 26339。复杂的是此 XML 中的几个命名空间。
    • @engineersmnky,感谢您的建议,但我也尝试了该方法,但没有成功。它什么也不返回。
    • @engineersmnky,是的,它的工作原理如下: require "nokogiri" doc = Nokogiri::XML(File.open("itis.xml")) doc.remove_namespaces! tsn = doc.xpath("//tsn") puts tsn 但是我怎样才能摆脱输出中的 呢?
    【解决方案2】:

    所以问题在于您的 XML 包含命名空间。

    有两种选择:

    1. 删除命名空间
    doc.remove_namespaces! 
    doc.at_xpath("//tsn") 
    #=> #<Nokogiri::XML::Element:0x2add795ea3b8 name="tsn" children=[#<Nokogiri::XML::Text:0x2add795e5f70 "26339">]>
    
    1. 引用命名空间:
    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">]>
    

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

    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"]
    

    Example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-12
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      相关资源
      最近更新 更多