如何将Nokogiri HTML节点转换为JSON

时间:2015-09-25 08:15:15

标签: ruby nokogiri

我输出HTML节点(Nokogiri :: XML :: Element< Nokogiri :: XML :: Node),如下所示:

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

2 个答案:

答案 0 :(得分:0)

试试这个:

Hash.from_xml(prog_element.to_xml).to_json

答案 1 :(得分:0)

如果您的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,你可以利用其他宝石或使用Rails&#39;在Active Support's core extensions to Hash中找到from_xml,但未在此处记录。它记录在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这样的工具直接操作更糟糕,因此它的存在。