使用 Nokogiri,我们可以编写以下代码:
require 'inflector'
require 'nokogiri'
def get_xml_stuff(xml, singular)
plural = Inflector.pluralize(singular)
return_hash = {plural => []}
xml.xpath("*/#{plural}/#{singular}").each { |tag| return_hash[plural] << tag.text}
return return_hash
end
根据我的测试,这解决了与您的 XmlSimple 代码匹配的简单案例。对于您的进一步要求:
如果 nodexyzs
包含一个或多个具有名称的子节点xyz
(并且没有其他节点),则 nodexyzs
应表示为结果哈希中的一个数组,带有名称xyzs
(并且数组的每个元素都应该是相应xyz
元素的内容)。
def get_xml_stuff(xml, singular)
plural = Inflector.pluralize(singular)
return_hash = {plural => []}
path = xml.xpath("*/#{plural}/#{singular}")
path.each { |tag| return_hash[plural] << tag.text} unless path.size != xml.xpath("*/#{plural}/*").children.size
return return_hash
end
但是,如果同一个复数在文件中出现多次,这仍然不完美。
回答UPD2。我的新版本功能如下:
def get_xml_stuff(xml, plural)
singular = Inflector.singularize(plural)
return_hash = {plural => []}
path = xml.xpath("./#{singular}")
path.each { |tag| return_hash[plural] << tag.text} unless path.size != xml.xpath("./*").size
return return_hash
end
在这里,我们从复数父节点开始,如果所有命名的子节点都具有该单数名称,则收集所有单数子节点。我的新测试代码变为:
sample_xml = Nokogiri::XML(sample_xml_text)
sample_xml.children.xpath("*").each do |child|
array = get_xml_stuff(child, child.name)
p array
end
如果没有像我的示例这样的标签<pets>
,则以下内容应该有效:
sample_xml = Nokogiri::XML(sample_xml_text)
array = get_xml_stuff(sample_xml.children.first, sample_xml.children.first.name)
p array
结束UPD2
作为参考,我的测试是:
sample_xml_text = <<-sample
<pets>
<cats>
<cat>John</cat>
<cat>Peter</cat>
</cats>
<kitties>
<kitty>Tibbles</kitty>
<kitty>Meow-chan</kitty>
<kitty>Puss</kitty>
</kitties>
<giraffes>
<giraffe>Long Neck</giraffe>
</giraffes>
<dogs>
<dog>Rover</dog>
<dog>Spot</dog>
<cat>Peter</cat>
</dogs>
</pets>
sample
sample_xml = Nokogiri::XML(sample_xml_text)
array = get_xml_stuff(sample_xml, "cat")
p array
array = get_xml_stuff(sample_xml, "kitty")
p array
array = get_xml_stuff(sample_xml, "giraffe")
p array
array = get_xml_stuff(sample_xml, "dog")
p array