我有一些解析后的Nokogiri::XML::Document对象,希望打印为json。
我可以让它成为一个字符串,将它解析成一个散列,使用活动记录或crack,然后使用hash.to_json;但是这既难看又取决于太多的manay库。
难道没有更简单的方法吗?
根据注释中的请求,例如xml<root a="b"><a>b</a></root>可以表示为json:

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

这就是我现在得到的裂纹。当然,实体和子标记之间的冲突是一个潜在的问题,但是我自己构建了大部分XML,所以最容易避免这些冲突:)

最佳答案

这里有一种方法。正如我的评论所指出的,正确的答案取决于你的输出应该是什么。JSON中没有XML节点的规范表示,因此相关库中没有内置这样的功能:

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

注意,上面的代码完全忽略了名称空间,这可能是您想要的,也可能不是您想要的。
转换为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 '<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"],"!"]]

关于ruby - 如何将Nokogiri Document对象转换为JSON,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6478005/

10-11 12:25