SOAP4R is the Ruby SOAP toolkit making it easy to prop up a web service or set up a client to access a remote API. Hpricot is an amazing HTML/XML parser. It has a C back-end and is extremely fast (I would say it’s faster then libxml wrapper in my opinion). But what happens when you want to send an XML document over SOAP without SOAP4R mucking it all up (in most cases SOAP4R will just choke and leave you with some obscure “Can’t translate crocodiles into SOAP::Object” message. Alas, in version 1.5.8 SOAP4R has the ability to simply wrap the XML and send it on its way.
Cool huh? Oh wait, you can only use REXML Documents/Elements for this, and as we all know REXML is not really a speed demon. Besides if the rest of your code uses Hpricot why switch to REXML and back again just for SOAP stuff. Well, the key in the paragraph describing the XML pass-through feature is “… or any class with ‘to_xmlpart’ method”. Hpricot::Doc doesn’t have ‘to_xmlpart’ method, but you wouldn’t really need out. Behold the following:
xml_container.rb:
class XMLContainer
def initialize(xml)
@xml = xml
end
def to_xmlpart
@xml
end
end
XMLContainer class has ‘to_xml’ method and thus can be passed directly into SOAP4R calls without the fear of blow-up:
require 'xml_container'
require 'hpricot'
require 'soap/rpc/driver'
# Do SOAP initialization here and get the RPC driver ready to make SOAP calls
# ...
xml_doc = Hpricot::XML(File.read("MyXML.xml"))
xml_can = XMLContainer.new xml_doc.to_html
soapdriver->add_method("SendStuff","myXml")
soapdriver->SendStuff xml_can
And there you go. Have fun kids
Correction: in the newest version of SOAP4R they changed the method from to_xml to to_xmlpart. I’ve update the code above to reflect that change.



September 25, 2007 at 6:52 pm |
You can just add the method to the class
require ‘hpricot’
class Hpricot
def to_xmlpart
self.to_html
end
end
create your hpricot object here.
Or
make your converter class inherits from Hpricot and extends its functionality.
class MyClass add_method(”SendStuff”,”myXml”)
soapdriver->SendStuff xml_doc
September 25, 2007 at 6:57 pm |
Eww it jacked up my comment.. Lets try this again.
Or
make your converter class inherits from Hpricot and extends its functionality.
class MyClass < Hpricot
def to_xmlpart
to_html
end
end
xml_doc=MyClass::XML(File.read(”MyXML.xml”))
soapdriver->add_method(”SendStuff”,”myXml”)
soapdriver->SendStuff xml_doc
September 25, 2007 at 6:58 pm |
Hpricot is a module, so it’s a little more tricky than that, but the idea is right. The upside to just having any string in the class is you can do things like:
xml = XMLContainer.new “#{@stuff}”
and then send it, which would essentially cut your processing time to 0ms.
September 25, 2007 at 7:05 pm |
You could then make a new module that extends the Hpricot module and implement to_xmlpart in your new module.
I’m not sure if you can inject a new method into a module, but I think that can be done as well.
September 26, 2007 at 12:03 am |
[...] 26th, 2007 Ok, after a bit a comment war on the previous port (SOAP4R with Hpricot) I feel the need to present a better way of dealing with XML pass-through using Hpricot. This is [...]