I am using Hpricot gem to parse xml. I am able to get title and pubdate but it did not work for link. Here is the code snippet
items = doc.search("//item").first(6)
items.each do |item|
feed = {}
feed[:title] = item.search("//title").text
feed[:link] = item.search("//link").text
feed[:published_date] = item.search("//pubdate").text
feeds << feed
end
The resultant hpricot elements are as follows:
#<Hpricot::Elements[{elem <item> "\n\t\t" {elem <title> "openagent.com.au" </title>} "\n\t\t" {emptyelem <link>} "http://blog.iproperty.com.au/2016/03/22/openagent-com-au/" {bogusetag </link>} "\n\t\t" {elem <comments> "http://blog.iproperty.com.au/2016/03/22/openagent-com-au/#comments" </comments>} "\n\t\t" {elem <pubdate> "Mon, 21 Mar 2016 22:43:28 +0000" </pubDate>} "\n\t\t"
I have pasted the initial part as it is the only part which is important. Can anyone tell what is the solution for it.
items = doc.search("//item").first(6)
items.each do |item|
feed = {}
feed[:title] = item.search("//title").text
feed[:link] = item.search("//link").innerHTML
feed[:published_date] = item.search("//pubdate").text
feeds << feed
end
for getting link we can use innerHTML
Related
All examples seen on the internet are XML files with structure like:
<open_tag>data that I want</close_tag>
but my XML file is different:
<Report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="_x0034_00_x0020_-_x0020_Nomenklatury" xsi:schemaLocation="_x0034_00_x0020_-_x0020_Nomenklatury http://pcisrs/ReportServer?%2FTARIC%20Reporty%20Ciselnikov%2F400%20-%20Nomenklatury&rs%3AFormat=XML&rc%3ASchema=True" Name="400 - Nomenklatury">
<table1>
<Detail_Collection>
<Detail goods_nomenclature_item_id="0100000000" product_line="80" date_start="31.12.1971" quantity_indents="0" declarable_import="0" declarable_export="0" goods_nomenclature_item_description="ŽIVÉ ZVIERATÁ"/>
<Detail goods_nomenclature_item_id="0101000000" product_line="80" date_start="01.01.1972" quantity_indents="1" statistical_unit="NAR" declarable_import="0" declarable_export="0" goods_nomenclature_item_description="Živé kone, somáre, muly a mulice" parent_goods_nomenclature_item_id="0100000000" parent_product_line="80"/>
.....ETC....
</Detail_Collection>
</table1>
</Report>
If I understand the tutorials, this should work:
subor = Nokogiri::XML(File.open('vendor/financnasprava/nomenklatury/recent.xml'))
dataset = subor.xpath('//Detail')
but didn't.
You can work with this data like in the example below. I removed the source path as I have not this data locally.
If i'm right and you are trying to the access Detail attributes:
require 'nokogiri'
require 'open-uri'
data_xml = <<-EOT
<Report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="400 - Nomenklatury">
<table1>
<Detail_Collection>
<Detail goods_nomenclature_item_id="0100000000" product_line="80" date_start="31.12.1971" quantity_indents="0" declarable_import="0" declarable_export="0" goods_nomenclature_item_description="ŽIVÉ ZVIERATÁ"/>
<Detail goods_nomenclature_item_id="0101000000" product_line="80" date_start="01.01.1972" quantity_indents="1" statistical_unit="NAR" declarable_import="0" declarable_export="0" goods_nomenclature_item_description="Živé kone, somáre, muly a mulice" parent_goods_nomenclature_item_id="0100000000" parent_product_line="80"/>
</Detail_Collection>
</table1>
</Report>
EOT
subor = Nokogiri::XML(data_xml)
dataset = subor.xpath('//Detail_Collection/*')
details = dataset.map do |row|
{
product_line: row.attributes['product_line'].value,
goods_nomenclature_item_id: row.attributes['goods_nomenclature_item_id'].value
}
end
puts details
#=> {:product_line=>"80", :goods_nomenclature_item_id=>"0100000000"}
#=> {:product_line=>"80", :goods_nomenclature_item_id=>"0101000000"}
I've got a bar graph that I'm trying to populate with a JSON response. I'm using Rails 5 with the built in JBuilder functionality.
Here is my code:
def graph_data
#customers = Customer.all
#graph_data = {graph_type: "Customer Growth"}
#months = {}
x = 5
while x >= 0
#months[x.months.ago.strftime("%B")] = current_account.customers.where(:created_at => x.months.ago.beginning_of_month..x.months.ago.end_of_month).count
x = x - 1
end
#graph_data[:months] = #months
puts #graph_data.to_json
end
The line puts #graph_data.to_json outputs the following text:
{"graph_type":"Customer Growth","months":{"November":0,"December":0,"January":0,"February":0,"March":0,"April":3}}
as I would expect.
However, when I output the actual JSON response in my graph_data.json.jbuilder file the output is
[["graph_type","Customer Growth"],["months",{"November":0,"December":0,"January":0,"February":0,"March":0,"April":3}]]
My goal was to get a response that looked more like this:
{"graph_type":"Customer Growth","months":["November":0,"December":0,"January":0,"February":0,"March":0,"April":3]}
but I don't know how to accomplish this with jBuilder.
Here are the contents of my graph_data.json.jbuilder file.
json.array! #graph_data
Thanks in advance.
In your jbuilder file, replace
json.array! #graph_data
to
json.graph_type #graph_data[:graph_type]
json.months #graph_data[:months]
I am new to ruby and rails programming and I need to parse an xml file that I get as a response and store the station names in an array. A sample of the xml is as follows :
<Stations>
<Station>
<Code>HT</Code>
<Type>knooppuntIntercitystation</Type>
<Namen>
<Kort>Den Bosch</Kort>
<Middel>'s-Hertogenbosch</Middel>
<Lang>'s-Hertogenbosch</Lang>
</Namen>
<Land>NL</Land>
<UICCode>8400319</UICCode>
<Lat>51.69048</Lat>
<Lon>5.29362</Lon>
<Synoniemen>
<Synoniem>Hertogenbosch ('s)</Synoniem>
<Synoniem>Den Bosch</Synoniem>
</Synoniemen>
</Station>
<Station>
<Code>HTO</Code>
<Type>stoptreinstation</Type>
<Namen>
<Kort>Dn Bosch O</Kort>
<Middel>Hertogenbosch O.</Middel>
<Lang>'s-Hertogenbosch Oost</Lang>
</Namen>
<Land>NL</Land>
<UICCode>8400320</UICCode>
<Lat>51.700553894043</Lat>
<Lon>5.3183331489563</Lon>
<Synoniemen>
<Synoniem>Hertogenbosch Oost ('s)</Synoniem>
<Synoniem>Den Bosch Oost</Synoniem>
</Synoniemen>
</Station>
</Stations>
I need to get the Code and the Lang name in an array of hashes or just the lang name in an array.
How can I do that in ruby ?
thanks in advance
you can use
hash = Hash.from_xml(xml)
Refrence doc:
http://apidock.com/rails/v4.0.2/Hash/from_xml/class
Here's a solution which doesn't require Rails but a small gem (xml-simple) :
# gem install xml-simple
require 'xmlsimple'
stations = XmlSimple.xml_in(xml, :ForceArray => ['Station', 'Synoniem'])
codes_and_langs = stations['Station'].map{|station| {:code => station["Code"], :lang => station.fetch("Namen",{})["Lang"]}}
puts codes_and_langs.inspect
#=> [{:code=>"HT", :lang=>"'s-Hertogenbosch"}, {:code=>"HTO", :lang=>"'s-Hertogenbosch Oost"}]
If you are using Rails or have Rails installed :
require 'active_support/core_ext/hash' # <- Use this line for non-Rails Ruby scripts.
hash = Hash.from_xml(xml)
root_node = hash["Stations"] || {}
stations = root_node["Station"] || []
codes_and_langs = stations.compact.map do |station|
{
:code => station["Code"],
:lang => station.fetch('Namen',{})['Lang']
}
end
puts codes_and_langs.inspect
#[{:code=>"HT", :lang=>"'s-Hertogenbosch"}, {:code=>"HTO", :lang=>"'s-Hertogenbosch Oost"}]
just_langs = stations.compact.map do |station|
station.fetch('Namen',{})['Lang']
end
puts just_langs.inspect
# ["'s-Hertogenbosch", "'s-Hertogenbosch Oost"]
Hash#fetch is used to avoid an exception if "Namen" isn't defined.
Here's xml variable for both scripts :
xml="<Stations>
<Station>
<Code>HT</Code>
<Type>knooppuntIntercitystation</Type>
<Namen>
<Kort>Den Bosch</Kort>
<Middel>'s-Hertogenbosch</Middel>
<Lang>'s-Hertogenbosch</Lang>
</Namen>
<Land>NL</Land>
<UICCode>8400319</UICCode>
<Lat>51.69048</Lat>
<Lon>5.29362</Lon>
<Synoniemen>
<Synoniem>Hertogenbosch ('s)</Synoniem>
<Synoniem>Den Bosch</Synoniem>
</Synoniemen>
</Station>
<Station>
<Code>HTO</Code>
<Type>stoptreinstation</Type>
<Namen>
<Kort>Dn Bosch O</Kort>
<Middel>Hertogenbosch O.</Middel>
<Lang>'s-Hertogenbosch Oost</Lang>
</Namen>
<Land>NL</Land>
<UICCode>8400320</UICCode>
<Lat>51.700553894043</Lat>
<Lon>5.3183331489563</Lon>
<Synoniemen>
<Synoniem>Hertogenbosch Oost ('s)</Synoniem>
<Synoniem>Den Bosch Oost</Synoniem>
</Synoniemen>
</Station>
</Stations>
"
I'm running an else loop to iterate through an XML file in ruby, assigning values to a hash. There are 3 items in the XML file, but for some reason it only iterates through the first one, any idea why?
require "nokogiri"
f= File.open("untitled.xml")
doc = Nokogiri::XML(f)
f.close
doc.xpath('//item').each do |node|
children = node.children
item = {
"name" => node['name'],
"buyItNowPrice"=> children.css('buytItNowPrice').inner_text,
"description" => children.css('description').inner_text,
"startingBidPrice" => children.css('startingBidPrice').inner_text,
"closing_time" => children.css('closing_time').inner_text,
"closing_date" => children.css('closing_date').inner_text
}
puts item
end
XML:
<item name = "Test Thing">
<description>Something Coolest.</description>
<buytItNowPrice>154.99</buytItNowPrice>
<startingBidPrice>9999.99</startingBidPrice>
<closing_date>2014-12-25</closing_date>
<closing_time>12:32:PM</closing_time>
</item>
<item name = "Lazer">
<description>Something Cool.</description>
<buytItNowPrice>149.99</buytItNowPrice>
<startingBidPrice>9.99</startingBidPrice>
<closing_date>2014-12-25</closing_date>
<closing_time>12:32:PM</closing_time>
</item>
<item name = "Pokemon">
<description>Something even cooler.</description>
<buytItNowPrice>33.99</buytItNowPrice>
<startingBidPrice>9.99</startingBidPrice>
<closing_date>2014-12-25</closing_date>
<closing_time>12:32:PM</closing_time>
</item>
Output is only the the first item printed.
The given sample XML isn't valid.
A valid XML document requires a single root node, right now you have 3.
You could fix this by wrapping all the <item> nodes in a <items> root node, and iterate through its children then.
def coderay(text)
text.gsub(/\<pre( )?\="" lang="(.+?)">\<code( )?\="" lang="(.+?)">(.+?)\<\/code\>\<\/pre\>/m) do
lang = $4
text = CGI.unescapeHTML($5).gsub /\<code( )?\="" lang="(.+?)">|\<\/code\>/, ""
text = text.gsub('<br />', "\n")
text = text.gsub(/[\<]([\/])*([A-Za-z0-9])*[\>]/, '')
text = text.gsub('>', ">")
text = text.gsub('<', "<")
text = text.gsub(' ', " ")
text = text.gsub('&', "&")
CodeRay.scan(text, lang).div(:css => :class)
end
end
The above generates this at the last closing "end":
</code(></code(></pre(>
Anyone knows why? I am using gems CodeRay 1.1.0 and RedCloth 4.2.9. Ruby version: 2.1.1 and Rails 3.2.19. RefineryCMS 2.1.3 and their blog engine.
I thought that this line was the cure but it is not:
text = CGI.unescapeHTML($5).gsub /\<code( )?\="" lang="(.+?)">|\<\/code\>/, ""
Edited:
This is in the show.html.erb file:
<%= raw (coderay(RedCloth.new(render 'post').to_html)) %>