usage parse instalar docs como ruby xml json nokogiri

ruby - parse - Cómo convertir el documento de Nokogiri en JSON



nokogiri parse xml (2)

Aquí hay una forma de hacerlo. Como he señalado en mi comentario, la respuesta ''correcta'' depende de lo que debería ser su salida. No hay una representación canónica de nodos XML en JSON y, por lo tanto, no existe tal capacidad incorporada en las bibliotecas involucradas:

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 ''<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" ] }, "!" ] } ] }

Tenga en cuenta que lo anterior ignora completamente los espacios de nombres, que pueden o no ser lo que usted desea.

Convertir a JsonML

Aquí hay otra alternativa que se convierte a JsonML. Si bien esta es una conversión con pérdida (no admite nodos de comentarios, DTD o URL de espacio de nombres) y el formato es un poco "torpe" por diseño (el primer elemento secundario está en [1] o [2] dependiendo de si o no hay atributos presentes), indica prefijos de espacio de nombres para elementos y atributos:

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 ''<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"],"!"]]

He analizado algunos objetos Nokogiri::XML::Document que deseo imprimir como JSON.

Puedo seguir la ruta para convertirla en una cadena, analizarla en un hash, con registro activo o Crack y luego Hash.to_json; pero eso es a la vez feo y dependiendo de muchas bibliotecas.

¿No hay una forma más sencilla?

Según la solicitud en el comentario, por ejemplo, el XML <root a="b"><a>b</a></root> podría representarse como JSON:

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

Eso es lo que consigo con Crack ahora también. Y, claro, las colisiones entre entidades y etiquetas de niños son un problema potencial, pero yo mismo construyo la mayoría del XML, por lo que es más fácil para mí evitar estas colisiones por completo :)


Esta funciona para mí:

Hash.from_xml(@nokogiri_object.to_xml).to_json

Este método utiliza el soporte activo, por lo tanto, si no está usando rieles, incluya las extensiones del núcleo de soporte activo manualmente:

require ''active_support/core_ext/hash''