![](/img/trans.png)
[英]How to convert a string `to_json` and `to_xml` using Ruby on Rails?
[英]Ruby - Convert XML to JSON without using Gems
我最近進行了一次編碼練習,涉及將XML轉換為JSON。 執行此操作的理智方法可能是使用JSON和ActiveSupport gem ,如此處所述。 那是我在生產中要做的,但這並不能使我成為更好的編碼器。 因此,我整理了自己的腳本,它可以正常工作,但是坦率地說,我認為它很丑陋。 我的問題是,怎么會更好? 我可以使用什么類型的技術和方法來使此腳本更簡單,更易讀和更專業?
作為參考,我們從以下input.html (干凈-無邊緣情況)開始:
<html>
<body>
<ul>
<li>Item One</li>
<li>Item Two</li>
<li>
<ul>
<li>A</li>
<li>B</li>
</ul>
</li>
</ul>
</body>
</html>
JSON輸出如下所示:
{ "html": { "body": { "ul": { "li": ["Item One", "Item Two", { "ul": { "li": ["A", "B"] } } ] } } }
這是腳本-* xml_to_json.rb *:
#!/usr/bin/env ruby
def ucode_strip(obj)
#remove weird whitespace
return obj.gsub(/\A[[:space:]]+|[[:space:]]+\z/, '')
end
def element?(obj)
#returns true if text is an xml element --e.g. "<html>"
if ucode_strip(obj) =~ /\A<.*?>/
true
end
end
def element(obj)
#returns html element name --e.g. "<html>" => html, "html" => nil
stripped = ucode_strip(obj)
parts = stripped.split(/>/)
return parts[0].sub(/</, '')
end
def value?(obj)
#does the line contain information inside of tags <tag>value</tag>
parts = obj.split(/>/)
unless !parts[1]
true
end
end
def value(obj)
#returns the value of an xml element --e.g. "<li>item</li>" => "item"
parts = obj.split(/\</)
parts[0]
end
def convert_file(file)
text = File.read(file.to_s)
lines = text.split(/\n/)
last_tag = nil
same_tags = nil
multiple_values = []
json = "{ "
lines.each do |line|
clean = ucode_strip(line)
if line =~ /<.*?>/
unless clean =~ /\A<\// #<opening tag>
line_elements = clean.split(/>/)
tag = "\"" + element(line) + "\"" + ':'
if line_elements[1]
#there's more data in this line, not just a tag
unless same_tags == true
same_tags = true
json += tag + " ["
last_tag = element(line)
else
json += ", "
end
json += "\"" + value(line_elements[1]) + "\""
else
#this line only contains an opening tag
same_tags = false #stop building list
unless element(line) == last_tag #the previous line started with the same tag
json += tag += " { "
else
json += ", { "
end
last_tag = tag
end
else #</closing tag>
if same_tags == true
#we have a closing tag while building a list
same_tags = false #stop building list
json += "] } " #first close list, then bracket
else
if clean =~ /#{last_tag}/
json += " } ] " #there's an open list we have to
else
json += " } " #no open list, just close bracket
end
end
end
end
end
return json
end
input = ARGV.first
puts convert_file(input)
如我所說,這可行,但我知道可能會更好。 我意識到幾乎沒有邊緣案例處理,但是我更關心整個數據的處理方式。 有人建議使用ruby列表作為堆棧來存儲嵌套的JSON,但我還沒有弄清楚。 任何幫助將不勝感激-如果您已經走了這么遠,感謝您的閱讀。
convert_file方法太復雜了,它將解析器和生成器的邏輯混合在一起,這使得讀取,重用和擴展變得困難,我建議將這一邏輯分離出來。
用於解析xml文件的代碼稱為解析器,據我所知,共有三種解析器,例如SAX,DOM,StAX,您可以通過google找到一些參考資料,看看如何實現。
用於生成json代碼的代碼稱為生成器,它是一種設計模式,您也可以通過Google找到更多信息。
堆棧是一個數據結構,您可以在實現解析器和構建器時使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.