Конвертер Ruby XML в JSON?

Есть ли библиотека для преобразования XML в JSON в Ruby?


person Lance Pollard    schedule 07.10.2009    source источник


Ответы (7)


Простой трюк:

Сначала вам нужно gem install json, затем при использовании Rails вы можете сделать:

require 'json'
require 'active_support/core_ext'
Hash.from_xml('<variable type="product_code">5</variable>').to_json #=> "{\"variable\":\"5\"}"

Если вы не используете Rails, вы можете gem install activesupport потребовать его, и все должно работать гладко.

Пример:

require 'json'
require 'net/http'
require 'active_support/core_ext/hash'
s = Net::HTTP.get_response(URI.parse('https://stackoverflow.com/feeds/tag/ruby/')).body
puts Hash.from_xml(s).to_json
person khelll    schedule 07.10.2009
comment
Иногда важно также сохранить атрибуты XML. Например, в приведенном выше примере был утерян product_code. Какую библиотеку или библиотеки вы бы предложили для сохранения атрибутов? - person David J.; 17.08.2010
comment
Обновление, если вы запускаете скрипт ruby ​​для того же, что и отдельная программа, чтобы избежать неопределенного метода from_xml. Вам необходимо включить require 'active_support/core_ext' , как указано здесь: - masonoise.wordpress.com/2010/01/07/hash-from_xml/#comments . В противном случае это отлично работает в Rails. - person boddhisattva; 20.04.2012
comment
Небольшое улучшение, чтобы получить красиво напечатанный JSON: JSON.pretty_generate(Hash.from_xml('<variable type="product_code">5</variable>')) - person Tom De Leu; 09.07.2013
comment
Это потрясающе, вероятно, сэкономило мне около 2 часов этим утром. - person dancow; 04.11.2013
comment
Обратите внимание, что вам нужно require 'json' и require 'active_support/core_ext', чтобы пример Тома Де Леу заработал. - person Ashley; 20.02.2015
comment
Обратите внимание, что вам нужно требовать «json» и «active_support/core_ext/hash», а НЕ «active_support/core_ext» - person etayluz; 29.05.2015
comment
Вам также необходимо преобразовать строку в хэш: eval(Hash.from_xml(s).to_json) - person etayluz; 29.05.2015

Я бы использовал Crack, простой анализатор XML и JSON.

require "rubygems"
require "crack"
require "json"

myXML  = Crack::XML.parse(File.read("my.xml"))
myJSON = myXML.to_json
person neilfws    schedule 01.10.2010

Если вы хотите сохранить все атрибуты, я рекомендую cobravsmongoose http://cobravsmongoose.rubyforge.org/, который использует соглашение о барсуке.

<alice sid="4"><bob sid="1">charlie</bob><bob sid="2">david</bob></alice>

становится:

{"alice":{"@sid":"4","bob":[{"$":"charlie","@sid":"1"},{"$":"david","@sid":"2"}]}}

код:

require 'rubygems'
require 'cobravsmongoose'
require 'json'
xml = '<alice sid="4"><bob sid="1">charlie</bob><bob sid="2">david</bob></alice>'
puts CobraVsMongoose.xml_to_hash(xml).to_json
person Corban Brook    schedule 27.01.2011

Вам может пригодиться xml-to-json gem. Он поддерживает атрибуты, инструкции по обработке и операторы DTD.

Установить

gem install 'xml-to-json'

Применение

require 'xml/to/json'
xml = Nokogiri::XML '<root some-attr="hello">ayy lmao</root>'
puts JSON.pretty_generate(xml.root) # Use `xml` instead of `xml.root` for information about the document, like DTD and stuff

Производит:

{
  "type": "element",
  "name": "root",
  "attributes": [
    {
      "type": "attribute",
      "name": "some-attr",
      "content": "hello",
      "line": 1
    }
  ],
  "line": 1,
  "children": [
    {
      "type": "text",
      "content": "ayy lmao",
      "line": 1
    }
  ]
}

Это простая производная от xml-to-hash.

person Maarten    schedule 14.06.2015

Если вам нужна скорость, я бы порекомендовал Ox, так как это самый быстрый вариант из уже существующих. упомянул.

Я выполнил несколько тестов, используя XML-файл размером 1,1 МБ с сайта omg.org/spec и вот результаты (в секундах):

xml = File.read('path_to_file')
Ox.parse(xml).to_json                    --> @real=44.400012533
Crack::XML.parse(xml).to_json            --> @real=65.595127166
CobraVsMongoose.xml_to_hash(xml).to_json --> @real=112.003612029
Hash.from_xml(xml).to_json               --> @real=442.474890548
person Dan F.    schedule 10.05.2017

Предполагая, что вы используете libxml, вы можете попробовать вариант этого (отказ от ответственности, это работает для моего ограниченного варианта использования, может потребоваться настройка, чтобы он был полностью универсальным)

require 'xml/libxml'

def jasonized
  jsonDoc = xml_to_hash(@doc.root)
  render :json => jsonDoc
end

def xml_to_hash(xml)
  hashed = Hash.new
  nodes = Array.new

  hashed[xml.name+"_attributes"] = xml.attributes.to_h if xml.attributes?
  xml.each_element { |n| 
    h = xml_to_hash(n)
    if h.length > 0 then 
      nodes << h 
    else
      hashed[n.name] = n.content
    end
  }
  hashed[xml.name] = nodes if nodes.length > 0
  return hashed
end
person erwin    schedule 22.02.2011
comment
самодельные кодовые решения, как правило, плохая идея для общих проблем, за исключением учебных целей. Особенно, когда речь идет конкретно о существующей библиотеке. - person Titou; 04.11.2014

Простой, но с тяжелыми зависимостями (active_support); это не большая проблема, если вы уже работаете в среде Rails.

require 'json'
require 'active_support/core_ext'

Hash.from_xml(xml_string).to_json

В противном случае, вероятно, было бы лучше использовать ox или rexml, чтобы иметь гораздо более легкие зависимости и большую производительность.

person Alex V    schedule 04.12.2019
comment
На самом деле это хелл-анвсер, и для использования from_xml требуется active_support, что является довольно большой внешней зависимостью. json также требуется для to_json, даже если это стандартная библиотека, поэтому мы можем сказать, что она нативная. - person noraj; 26.05.2021