XPath Nested Nodes - ruby-on-rails

I need to loop and get the updates that belong to each lot, but when I use xmldoc.xpath("//update") it just gives me all of the updates even if not nested into the lot. How can I get the updates that are nested in to the selected lot only?
lots = xmldoc.xpath("//lot")
lots.each do |lot|
#lot = Lot.new
#lot.legacy_id = lot.at("legacy_id").text
#lot.event = #event
#lot.group = lot.at("group").text
#lot.number = lot.at("number").text
#lot.title = lot.at("title").text
#lot.description = lot.at("description").text
#lot.price = lot.at("price").text
#lot.start_at = lot.at("start_at").text
#lot.end_at = lot.at("end_at").text
#lot.position = lot.at("position").text
#lot.notes = lot.at("notes").text
#lot.save
updates = xmldoc.xpath("//update")
updates.each do |update|
#lot_update = LotUpdate.new
#lot_update.save
end
end
XML:
<?xml version="1.0" encoding="UTF-8" ?>
<event>
<legacy_id>54321</legacy_id>
<lots>
<lot>
<legacy_id>12345</legacy_id>
<number>1</number>
<title>Big Cow</title>
<description>A big cow</description>
<position>1</position>
<price>500</price>
<start_at>2013-02-15 10:00:00</start_at>
<end_at>2013-02-15 12:00:00</end_at>
<group>1</group>
</lot>
</lots>
<lots>
<lot>
<legacy_id>12346</legacy_id>
<number>1</number>
<title>Small Cow</title>
<description>A small cow</description>
<position>1</position>
<price>500</price>
</lot>
</lots>
</event>

You want lot.xpath('.//update').

Related

How to parse XML with non-pair tags using Nokogiri

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"}

QBOv3 XML Validation Fault 2500 (Invalid Reference Id )

I'm trying to create a test invoice at quickbooks using quickbooks-ruby gem. Note I have a test account at QB which doesn't have anything: invoice, customer, etc. It's a new account created only for testing purpose. So here is my code:
service = Quickbooks::Service::Invoice.new
service.company_id = current_user.company_id
service.access_token = create_consumer
qb_invoice = Quickbooks::Model::Invoice.new
qb_invoice.customer_id = 123
line_item = Quickbooks::Model::InvoiceLineItem.new
line_item.amount = 100
line_item.sales_item! do |detail|
detail.unit_price = 100
detail.quantity = 1
detail.item_id = 1
end
qb_invoice.line_items << line_item
res = service.create qb_invoice
p res.id #exception!
def create_consumer
OAuth::AccessToken.new(.....)
end
Request:
METHOD = post
RESOURCE = https://qb.sbfinance.intuit.com/v3/company/fdsfdsfdsfds123/invoice
<?xml version="1.0" encoding="utf-8"?>
<Invoice xmlns="http://schema.intuit.com/finance/v3" sparse="false">
<Line>
<Amount>100.0</Amount>
<DetailType>SalesItemLineDetail</DetailType>
<SalesItemLineDetail>
<ItemRef>1</ItemRef>
<UnitPrice>100.0</UnitPrice>
<RatePercent>0.0</RatePercent>
<Qty>1.0</Qty>
</SalesItemLineDetail>
</Line>
<CustomerRef>123</CustomerRef>
<TotalAmt>0.0</TotalAmt>
<Balance>0.0</Balance>
<Deposit>0.0</Deposit>
</Invoice>
and response with the error:
RESPONSE CODE = 400
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2014-03-06T19:30:49.168-08:00">
<Fault type="ValidationFault">
<Error code="2500" element="">
<Message>Invalid Reference Id</Message>
<Detail>Invalid Reference Id : Something you're trying to use has been deleted. Check the fields with accounts, customers, items, vendors or employees.
</Detail>
</Error>
</Fault>
</IntuitResponse>
Could it be because a customer with id = 123 doesn't exist? If not, what's the cause then?
Please check if you have a customer(ID-123) and Item(Id-1) exist in your account.
If not then create these two entries using apiexplorer/code and use the corresponding object IDs.
ApiExplorer - https://developer.intuit.com/apiexplorer?apiname=V3QBO
EntityRef - https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/030_entity_services_reference
ApiExplorer -
Ref - https://developer.intuit.com/docs/0025_quickbooksapi/0010_getting_started/0015_firstrequest
Thanks

How do I send information from controller method to HTML page?

I am developing a Rails application and want to put some info that I already read from an XML file and show it in a new page.
In my view I have:
<%= link_to 'Hoteles', :method => :hotels %>
and the controller method is:
def hotels
url = "http://api.hotelsbase.org/search.php?longitude="+#city_visit.longitude+"&latitude="+#city_visit.latitude
data = Nokogiri::HTML(open(url))
$name = data.xpath("//name")
$fulladdress = data.xpath("//fulladdress")
$phone = data.xpath("//phone")
$city = data.xpath("//city")
$description = data.xpath("//description")
$featured = data.xpath("//featured")
$stars = data.xpath("//stars")
$rating = data.xpath("//rating")
$long = data.xpath("//long")
$lat = data.xpath("//lat")
$dist = data.xpath("//dist")
$price = data.xpath("//price")
$tripadvisorurl = data.xpath("//tripadvisorurl")
$url = data.xpath("//url")
$hotelsbaseUrl = data.xpath("//hotelsbaseUrl")
end
Now I want to show that information in a HTML page.
All the global variables (starting with a $) you've defined should be instance variables (starting with an #)
#name = data.xpath("//name")
#fulladdress = data.xpath("//fulladdress")
And then you can use them in the hotels.html.erb view, like this
<%= #name %>
You should look at Rails guides to find more information and good practices about Rails; the one called "Layouts and Rendering in Rails" would have helped you for this question.

Wrong Number of Arguments

I understand what causes the wrong number of arguments error but my code doesn't pass any parameters to initialize any of the classes so I'm not sure at all why my code is giving me this error. I'm also pretty new to Ruby on Rails so that doesn't help things. My code is below:
def create_google_file
#products = Product.find(:all)
file = File.new('dir.xml','w')
doc = REXML::Document.new
root = REXML::Element.new "rss"
root.add_attribute("xmlns:g", "http://base.google.com/ns/1.0")
root.add_attribute("version", "2.0")
channel = REXML::Element.new "channel"
root.add_element channel
title = REXML::Element.new "title"
title.text = "Sample Google Base"
channel.add_element title
link = REXML::Element.new "link"
link.text = "http://base.google.com/base/"
channel.add_element link
description = REXML::Element.new "description"
description.text = "Information about products"
channel.add_element description
#products.each do |y|
item = channel.add_element("item")
id = item.add_element("g:id")
id.text = y.id
title = item.add_element("title")
title.text = y.title
description = item.add_element("description")
description.text = y.description
googlecategory = item.add_element("g:google_product_category")
googlecategory.text = y.googlecategory
producttype = item.add_element("g:product_type")
producttype.text = y.producttype
link = item.add_element("link")
link.text = y.link
imglink = item.add_element("g:image_link")
imglink.text = y.imglink
condition = item.add_element("condition")
condition.text = y.condition
availability = item.add_element("g:availability")
availability.text = y.availability
price = item.add_element("g:price")
price.text = y.price "USD"
gtin = item.add_element("g:gtin")
gtin.text = y.gtin
brand = item.add_element("g:brand")
brand.text = y.brand
mpn = item.add_element("g:mpn")
mpn.text = y.mpn
expirationdate = item.add_element("g:expiration_date")
expirationdate.text = y.salepricedate
end
doc.add_element root
file.puts doc
file.close
end
The error I'm getting is:
ArgumentError in ProductsController#create_google_file
wrong number of arguments (1 for 0)
At the request of the poster, I am putting my comments in to an answer:
Based purely on the consistency of the other lines, but without knowing which line is actually failing, it may be this part: price.text = y.price "USD". Is y.price a method that takes in a parameter? Is it defined as def price(type) or something? If not, if it doesn't take any parameters, then it's because you're not supposed to send any parameters to that method. It looks like it's just a getter.
#FranklinJosephMoormann As I suspected, that's the line. Were you trying to make a string like "4.50 USD"? Then you probably wanted: price.text = "#{y.price} USD". That will take the result of y.price and put it in a string, and allow you to keep typing more in the string. It's called string interpolation.

Read response with Nokogiri from a SOAP call with Savon

I have make a soap-call with Savon. This works fine and give the
following response:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://
schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetTop10Response xmlns="http://www.kirupafx.com">
<GetTop10Result>
<string>string</string>
<string>string</string>
</GetTop10Result>
</GetTop10Response>
</soap:Body>
</soap:Envelope>
Now I want to take all of the string elements out of the response. But
I can't get it to work.
def query(params=nil)
client = Savon::Client.new do
wsdl.document = "http://www.kirupafx.com/WebService/TopMovies.asmx?wsdl"
end
response = client.request :get_top10
if response.success?
xml = Nokogiri::XML(response.to_xml)
print "Until here oké!"
xml.search('//GetTop10Result').each do |result|
print "How are you Ruby?"
#result[result.at('string').inner_text] = result.at('string').inner_text
end
else
raise "Error!"
end
But he never prints my beautiful "How are you Ruby?" Can somebody help
me? What I'm doing wrong?
You could to this but this isnt the best way to deal with problems like this! You might have experience using Nokogiri and XML but its easier to use .to_hash like this.
def query
client = Savon::Client.new do
wsdl.document = "http://www.kirupafx.com/WebService/TopMovies.asmx?wsdl"
end
response = client.request(:get_top10)
response.to_hash[:get_top10_response][:get_top10_result] if response.success?
false
end
Thanks for both reactions! I figured out. Here is my code:
# Prepare SOAP-request
client = Savon::Client.new do
wsdl.document = "http://www.kirupafx.com/WebService/TopMovies.asmx?wsdl"
end
# Execute SOAP-request
response = client.request :get_top10
if response.success?
names = Array.new(10)
index = 0
hash = response.to_hash[:get_top10_response][:get_top10_result][:string]
hash.each do |value|
names[index] = value
index += 1
end
#result = {
"0"=>{"name"=>"#{names.at(0)}"},
"1"=>{"name"=>"#{names.at(1)}"},
"2"=>{"name"=>"#{names.at(2)}"},
"3"=>{"name"=>"#{names.at(3)}"},
"4"=>{"name"=>"#{names.at(4)}"},
"5"=>{"name"=>"#{names.at(5)}"},
"6"=>{"name"=>"#{names.at(6)}"},
"7"=>{"name"=>"#{names.at(7)}"},
"8"=>{"name"=>"#{names.at(8)}"},
"9"=>{"name"=>"#{names.at(9)}"}
}
else
raise "Error occurred during the request to the top 10 movies!"
end

Resources