Ruby Forum Ruby on Rails > extract and assign xml values to variable

Posted by Dhaval Phansalkar (dhaval)
on 05.05.2008 08:26
hi,
   how can we assign an xml element value to some variable in
controller? e.g. if we have
<order>
   <id>1</id>
   <name>abc</name>
   <location>xyz</location>
</order>
and if we want value of name i.e. 'abc' to be assigned in a variable
declared in a controller, say order_controller, like this- temp = "value
of xml element name i.e. abc".
how can we do that? thanks in advance :)

-Dhaval
Posted by Thorsten Mueller (thorsten)
on 05.05.2008 11:28
Posted by Dhaval Phansalkar (dhaval)
on 05.05.2008 11:48
hi,
   thanks for the link Thorsten. in my application, i'm using builder. 
actually, i could generate an xml, post it and get a response in xml 
only. what i want to know is, thr is an element called result having 
either success or fail value and i want to show a msg depending upon the 
value. like if it has success the msg may be "action processed" or if 
its fail then msg may be "action failed" something like that. can you 
help me in this pls?

P.S.:- the xml request generation and response code is written in model 
and it sends request in xml and gets response in xml. i need to have the 
result's value in its controller. i hope i've provided the required 
details.

-Dhaval
Posted by Kyle (Guest)
on 05.05.2008 21:45
(Received via mailing list)
I'm not sure if you really should have that in your model, but here's
what I have in my controller to check for a successful FedEx rate
available request.  Get ready for some ugly code that works:

@resp, @data = h.post(path, xmlrequest, headers)
doc = REXML::Document.new(@data)
if doc.root.elements["HighestSeverity"] &&
doc.root.elements["HighestSeverity"].text.upcase == 'SUCCESS'
  services = REXML::XPath.match(doc, "//ServiceType")
  @services_and_rates = services.collect do |s|
    [s.text,
s.parent.parent.elements["RatedShipmentDetails"].elements["ShipmentRateDetail"].elements["TotalNetCharge"].elements["Amount"].text.to_f
+ (0.006 * @cart.total_price.to_f)]
  end
end

I'm sure that there are better ways to do this, but this worked when I
had to figure it out.  Essentially, I'm checking for a value of
"SUCCESS" in the only "HighestSeverity" container in the response.  If
it was successful, I go on and look for each value for "ServiceType".
I match the text of the service type with the rate by traversing using
a series of child and parent functions.  I create an array for later
use.

Somebody once mentioned (I think) that you might be able to check XML
values by looking in the params of the response.  I'd look into that
if I were you.

-Kyle


On May 5, 4:48 am, Dhaval Phansalkar <rails-mailing-l...@andreas-
Posted by Dhaval Phansalkar (dhaval)
on 07.05.2008 17:47
hi,
   thanks Kyle. that help me. i'd the same case in my response, 
"success" or "failure", and i could get this now. but now the next prb 
is, i need to print the values from the response itself on the page(as 
if we do for any other object using for loop), if the response is 
success. e.g. if response has success and the values as  -
<order>
   <id>1</id>
   <personalDetails>
      <firstName>abc</firstName>
      <lastName>def</lastName>
      <locationName>xyz</locationName>
   </personalDetails>
   <address>
      <bldg>21</bldg>
      <street>asd</street>
      <city>qwe</city>
      <state>zxc</state>
   </address>
</order>

then i need to print it as
   First Name    : abc
   Last Name     : def
   Location Name : xyz
   Building      : 21
   street        : asd
   city          : qwe
   state         : zxc

   i tried to print the response directly, but that printed all values 
in single line without a space. i also searched on internet, but 
couldn't find anything with such requirement. is thr a way to get such 
an output? Thanks in adv :)

-Dhaval
Posted by Kyle (Guest)
on 09.05.2008 00:00
(Received via mailing list)
Yes, you can do that.  Read up a bit on REXML or other XML parsing
engines for Rails.  My example above finds the "ServiceType"
container, goes to its parent, then its parent, then its child named
"RatedShipmentDetails", its child named "ShipmentRateDetail", its
child named "TotalNetCharge", and finally, its child "Amount".  To get
the value, I used .text to specify that I want what's inside of the
container.

Essentially, you can create a REXML document based on "//order//id"
and assign values the same way:

first_name =
doc.root.elements["personalDetails].elements["firstName"].text
last_name = ...

You get the idea.  I'm sure that there are better ways to do this, so
please look around.  Thorsten mentioned hpricot earlier, so see if it
will better suit your needs.  Try to see if params["order"]["id"]
["personalDetails"]["firstName"] can get you what you're looking for.
All in all, look around.  I didn't pay much attention to the "best"
way to do things when I wrote a lot of my first code, and now I have a
hard-to-maintain app.  See what you can find that might work better
than what I've given you.

-Kyle

On May 7, 10:47 am, Dhaval Phansalkar <rails-mailing-l...@andreas-
Posted by Dhaval Phansalkar (dhaval)
on 09.05.2008 06:07
hi,
   thanks kyle, u mentioned the details very well. actually i have 
almost 50 fields in my response xml, so was finding some better and 
proper way to do it rather than putting each element in seperate 
variable. but anyways, i'll keep searching the better way and will put 
it here if i find any. for time being, i'll use this method only.
   thanks once again :)

-Dhaval