如何将Nokogiri Document对象转换为JSON

我有一些解析Nokogiri::XML::Document对象,我想打印为JSON。

我可以把它变成一个字符串,将其解析为哈希,使用active-record或Crack,然后是Hash.to_json; 但这既丑陋又依赖于manay库。

有没有更简单的方法?

根据评论中的请求,例如XML b可以表示为JSON:

 b #=> {"root":{"a":"b"}} b #=> {"root":{"a":"b","foo":"bar"}} 

这也是我现在用Crack得到的。 实际上,实体和子标签之间的冲突是一个潜在的问题,但我自己构建了大部分XML,因此最简单的方法就是完全避免这些冲突:)

这是一种方法。 正如我的评论所指出的,“正确”的答案取决于你的输出应该是什么。 JSON中没有XML节点的规范表示,因此所涉及的库中没有构建这样的function:

 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) end end class Nokogiri::XML::Document def to_json(*a); root.to_json(*a); end end class Nokogiri::XML::Text def to_json(*a); text.to_json(*a); end end class Nokogiri::XML::Attr def to_json(*a); value.to_json(*a); end end xml = Nokogiri::XML ' Hello World! ' 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" ] }, "!" ] } ] } 

请注意,上面完全忽略了名称空间,这可能是您想要的,也可能不是。


转换为JsonML

这是另一种转换为JsonML的替代方案。 虽然这是一个有损转换(它不支持注释节点,DTD或命名空间URL),并且格式有点“傻”设计(第一个子元素在[1][2]取决于是否或不存在属性),它确实指示元素和属性的名称空间前缀:

 require 'nokogiri' require 'json' class Nokogiri::XML::Node def namespaced_name "#{namespace && "#{namespace.prefix}:"}#{name}" end end class 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) end end class Nokogiri::XML::Document def to_json(*a); root.to_json(*a); end end class Nokogiri::XML::Text def to_json(*a); text.to_json(*a); end end class Nokogiri::XML::Attr def to_json(*a); value.to_json(*a); end end xml = Nokogiri::XML ' Hello World! ' puts xml.to_json #=> ["root",{"a":"b"},["z:a","Hello ",["b",{"z:x":"y"},"World"],"!"]] 

这对我有用:

 Hash.from_xml(@nokogiri_object.to_xml).to_json 

此方法使用主动支持,因此,如果您不使用rails,则手动包含活动支持核心扩展