如何在Ruby中将部分XML转换为哈希

时间:2015-04-25 06:45:21

标签: ruby xml xml-parsing nokogiri

我有一个字符串,其中包含纯文本和额外的空格和回车符,然后是XML标记,后跟XML标记:

String = "hi there.

<SET-TOPIC> INITIATE </SET-TOPIC>

<SETPROFILE>
   <KEY>name</KEY>
   <VALUE>Joe</VALUE>
</SETPROFILE>

 <SETPROFILE>
   <KEY>email</KEY>
   <VALUE>Email@hi.com</VALUE>
</SETPROFILE>

<GET-RELATIONS>
  <COLLECTION>goals</COLLECTION>
  <VALUE>walk upstairs</VALUE>
</GET-RELATIONS>
So what do you think?

Is it true?
 "

我想解析类似于使用Nori或Nokogiri或Ox,他们将XML转换为哈希。

我的目标是能够轻松地将顶级标签作为键拉出,然后知道所有元素,例如:

Keys = ['SETPROFILE', 'SETPROFILE', 'SET-TOPIC', 'GET-OBJECT']

Values[0] = [{name => Joe}, {email => email@hi.com}]
Values[3] = [{collection => goals}, {value => walk up}]

我已经看到了类似于真正XML的几个函数,但我的所有函数都是部分的。

我开始思考这条思路:

parsed = doc.search('*').each_with_object({}) do |n, h| 
  (h[n.name] ||= []) << n.text 
end

2 个答案:

答案 0 :(得分:1)

如果我想要before_actionkeys变量,我可能会沿着这些方向做点什么:

values

require 'nokogiri' string = "hi there. <SET-TOPIC> INITIATE </SET-TOPIC> <SETPROFILE> <KEY>name</KEY> <VALUE>Joe</VALUE> </SETPROFILE> <SETPROFILE> <KEY>email</KEY> <VALUE>Email@hi.com</VALUE> </SETPROFILE> <GET-RELATIONS> <COLLECTION>goals</COLLECTION> <VALUE>walk upstairs</VALUE> </GET-RELATIONS> So what do you think? Is it true? " doc = Nokogiri::XML('<root>' + string + '</root>', nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS) nodes = doc.root.children.reject { |n| n.is_a?(Nokogiri::XML::Text) }.map { |node| [ node.name, node.children.map { |c| [c.name, c.content] }.to_h ] } nodes # => [["SET-TOPIC", {"text"=>" INITIATE "}], # ["SETPROFILE", {"KEY"=>"name", "VALUE"=>"Joe"}], # ["SETPROFILE", {"KEY"=>"email", "VALUE"=>"Email@hi.com"}], # ["GET-RELATIONS", {"COLLECTION"=>"goals", "VALUE"=>"walk upstairs"}]] 可以获取剩下的细节:

nodes

如果您愿意,可以预先处理DOM并删除顶级文字:

keys = nodes.map(&:first)
# => ["SET-TOPIC", "SETPROFILE", "SETPROFILE", "GET-RELATIONS"]

values = nodes.map(&:last)
# => [{"text"=>" INITIATE "},
#     {"KEY"=>"name", "VALUE"=>"Joe"},
#     {"KEY"=>"email", "VALUE"=>"Email@hi.com"},
#     {"COLLECTION"=>"goals", "VALUE"=>"walk upstairs"}]

values[0] # => {"text"=>" INITIATE "}

这样可以更轻松地使用XML。

答案 1 :(得分:0)

将字符串内容包装在节点中,您可以使用Nokogiri解析它。 XML段外的文本将是新节点中的文本节点。

str = "hi there. .... Is it true?"
doc = Nokogiri::XML("<wrapper>#{str}</wrapper>")
segments = doc.xpath('/*/SETPROFILE')

现在您可以使用&#34; Convert a Nokogiri document to a Ruby Hash&#34;将段转换为哈希值。

但是,如果纯文本中包含一些需要在XML规范中进行转义的字符,那么您需要找到这些字符并自行转义。