【问题标题】:How to convert Nokogiri HTML node into JSON如何将 Nokogiri HTML 节点转换为 JSON
【发布时间】:2015-09-25 08:15:15
【问题描述】:

我输出 HTML 节点(Nokogiri::XML::Element

<prog>
  <prog_name>Barclay CTA Index</prog_name>
  <prog_id>9</prog_id>
</prog>

我想得到像这样的哈希:

{
    prog_name: "Barclay CTA Index"
    prog_id: 9
}

to_hash 方法不起作用:

[3] pry(main)> prog_element.to_hash
[]

【问题讨论】:

    标签: ruby nokogiri


    【解决方案1】:

    试试这个:

    Hash.from_xml(prog_element.to_xml).to_json
    

    【讨论】:

    • 不是from_xml rails 特定的吗?
    • 如果您要在非 Rails 问题中推荐使用 Rails 方法,则需要说明如何访问它。简单地将方法扔到代码中只会增加混乱。
    【解决方案2】:

    如果您的 XML 很简单,那么构建散列很容易:

    require 'json'
    require 'nokogiri'
    
    xml = <<EOT
    <prog>
      <prog_name>Barclay CTA Index</prog_name>
      <prog_id>9</prog_id>
    </prog>
    EOT
    
    doc = Nokogiri::XML(xml)
    
    prog_name = doc.at('prog_name').text
    prog_id = doc.at('prog_id').text.to_i
    
    hash = {
      prog_name: prog_name,
      prog_id: prog_id
    }
    
    hash # => {:prog_name=>"Barclay CTA Index", :prog_id=>9}
    
    puts hash.to_json
    # >> {"prog_name":"Barclay CTA Index","prog_id":9}
    

    如果您的 XML 不是那么简单(应该在示例中反映出来),那么它会涉及更多:

    require 'json'
    require 'nokogiri'
    
    xml = <<EOT
    <xml>
      <prog>
        <prog_name>Barclay CTA Index</prog_name>
        <prog_id>9</prog_id>
      </prog>
      <prog>
        <prog_name>foo</prog_name>
        <prog_id>1</prog_id>
      </prog>
    </xml>
    EOT
    
    doc = Nokogiri::XML(xml)
    
    hash = {
      'prog' => []
    }
    
    doc.search('prog').each do |prog|
      prog_name = doc.at('prog_name').text
      prog_id = doc.at('prog_id').text.to_i
    
      hash['prog'] << {
        prog_name: prog_name,
        prog_id: prog_id
      }
    end
    
    hash
    # => {"prog"=>
    #      [{:prog_name=>"Barclay CTA Index", :prog_id=>9},
    #       {:prog_name=>"Barclay CTA Index", :prog_id=>9}]}
    
    puts hash.to_json
    # >> {"prog":[{"prog_name":"Barclay CTA Index","prog_id":9},{"prog_name":"Barclay CTA Index","prog_id":9}]}
    

    XML 往往比较冗长,而 JSON 则非常简洁,因此通常不需要将 XML 节点一对一映射到 JSON,从而允许我们选择 JSON 的外观。如果 XML 很大并且包含很多您不需要传递的数据,那将是一个很大的优势。

    如果您想逐字转换 XML,您可以利用其他 gem 或使用 Rails 的 from_xml,它在 Active Support's core extensions to Hash 中找到,但在那里没有记录。不过,它记录在Active Support Hash documentation 中:

    require 'active_support/core_ext/hash/conversions'
    require 'json'
    
    xml = <<EOT
    <xml>
      <prog>
        <prog_name>Barclay CTA Index</prog_name>
        <prog_id>9</prog_id>
      </prog>
      <prog>
        <prog_name>foo</prog_name>
        <prog_id>1</prog_id>
      </prog>
    </xml>
    EOT
    
    hash = Hash.from_xml(xml)
    # => {"xml"=>
    #      {"prog"=>
    #        [{"prog_name"=>"Barclay CTA Index", "prog_id"=>"9"},
    #         {"prog_name"=>"foo", "prog_id"=>"1"}]}}
    
    puts hash.to_json
    
    # >> {"xml":{"prog":[{"prog_name":"Barclay CTA Index","prog_id":"9"},{"prog_name":"foo","prog_id":"1"}]}}
    

    请注意,使用 from_xml 不会将 prog_id 值从字符串转换为整数,这意味着它们也将通过 JSON 序列化作为字符串传递。此外,如果 XML 中有不需要的节点,它们将被传递到 JSON,使其膨胀并减慢传输速度,因此您需要决定是要将其施加到用户的浏览器还是接收端。

    一旦您了解了 XML 和 Nokogiri,使用 Nokogiri 将 XML 转换为哈希并不难,掌握这些知识是您工具箱中的一套很好的工具。依赖from_xml 之类的东西是可以的,因为它很方便,但是你需要权衡这些知识和做自定义事情以及切片和切块的能力。操作和访问散列中的数据通常比直接使用像 Nokogiri 这样的工具更糟糕,因此它存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-28
      • 1970-01-01
      • 2011-09-22
      • 2014-07-16
      • 1970-01-01
      • 2023-03-12
      • 2020-07-17
      • 1970-01-01
      相关资源
      最近更新 更多