How to convert Nokogiri Document object into JSON
Here's one way to do it. As noted by my comment, the 'right' answer depends on what your output should be. There is no canonical representation of XML nodes in JSON, and hence no such capability is built into the libraries involved:
require 'nokogiri'require 'json'class Nokogiri::XML::Node def to_json(*a) {"$name"=>name}.tap do |h| kids = children.to_a h.merge!(attributes) h.merge!("$text"=>text) unless text.empty? h.merge!("$kids"=>kids) unless kids.empty? end.to_json(*a) endendclass Nokogiri::XML::Document def to_json(*a); root.to_json(*a); endendclass Nokogiri::XML::Text def to_json(*a); text.to_json(*a); endendclass Nokogiri::XML::Attr def to_json(*a); value.to_json(*a); endendxml = Nokogiri::XML '<root a="b" xmlns:z="zzz"> <z:a>Hello <b z:x="y">World</b>!</z:a></root>'puts xml.to_json
{ "$name":"root", "a":"b", "$text":"Hello World!", "$kids":[ { "$name":"a", "$text":"Hello World!", "$kids":[ "Hello ", { "$name":"b", "x":"y", "$text":"World", "$kids":[ "World" ] }, "!" ] } ]}
Note that the above completely ignores namespaces, which may or may not be what you want.
Converting to JsonML
Here's another alternative that converts to JsonML. While this is a lossy conversion (it does not support comment nodes, DTDs, or namespace URLs) and the format is a little bit "goofy" by design (the first child element is at [1]
or [2]
depending on whether or not attributes are present), it does indicate namespace prefixes for elements and attributes:
require 'nokogiri'require 'json'class Nokogiri::XML::Node def namespaced_name "#{namespace && "#{namespace.prefix}:"}#{name}" endendclass Nokogiri::XML::Element def to_json(*a) [namespaced_name].tap do |parts| unless attributes.empty? parts << Hash[ attribute_nodes.map{ |a| [a.namespaced_name,a.value] } ] end parts.concat(children.select{|n| n.text? ? (n.text=~/\S/) : n.element? }) end.to_json(*a) endendclass Nokogiri::XML::Document def to_json(*a); root.to_json(*a); endendclass Nokogiri::XML::Text def to_json(*a); text.to_json(*a); endendclass Nokogiri::XML::Attr def to_json(*a); value.to_json(*a); endendxml = Nokogiri::XML '<root a="b" xmlns:z="zzz"> <z:a>Hello <b z:x="y">World</b>!</z:a></root>'puts xml.to_json#=> ["root",{"a":"b"},["z:a","Hello ",["b",{"z:x":"y"},"World"],"!"]]