XML 元素中的连字符 (-) 在 Ruby 中将其转换为 JSON 时变为下划线 (_)

问题描述

我的 XML 元素的日期用连字符分隔并以下划线开头以保持 XML 有效。

<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <_2018-12-11>
    <USD>1.1379</USD>
    <JPY>128.75</JPY>
    <BGN>1.9558</BGN>
  </_2018-12-11>
  <_2018-12-10>
    <USD>1.1425</USD>
    <JPY>128.79</JPY>
    <BGN>1.9558</BGN>
  </_2018-12-10>
</root>

我使用 Nokogiri 和 Active Support 将文档转换为 JSON。这是代码:-

require 'json'
require 'nokogiri'
require 'active_support/core_ext/hash/conversions'
s = File.read('../data/currency_source.xml')
x = Nokogiri::XML(s)
newX = Hash.from_xml(x.to_s) #Even though I use Hash.from_xml(x).to_json,it throws an error "does not have a valid root"

puts JSON.pretty_generate(newX)

上面的代码以Hash形式打印信息,日期应该是_2018-12-11但它显示_2018_12_11

当我只打印 XML 时,它会正确显示日期元素,但在将其转换为 JSON 后无法正确显示

有什么我可以解决方法来以正确的格式获取日期,即用连字符而不是下划线分隔吗?

附言我也试过 Crack 和 CobraVsMongoose。 Crack 也产生了同样不受欢迎的日期格式。但是,CobraVsMongoose 正确维护了连字符,但它不必要地附加了 $ 符号。

解决方法

此转换在 .from_xml 的 ActiveSupport 代码中明确完成。从 source 中,转换后的散列的键被规范化以删除破折号:

def normalize_keys(params)
  case params
  when Hash
    Hash[params.map { |k,v| [k.to_s.tr("-","_"),normalize_keys(v)] } ]
  when Array
    params.map { |v| normalize_keys(v) }
  else
    params
  end
end

没有评论来解释为什么这是必要的或可取的,并且没有选项/开关可以跳过规范化。一种可能的解决方法是在 XML 源键中使用不同的分隔符(例如 _2018.12.10),然后在将它们安全地放入哈希后将它们转换为破折号。