From: Michael Shigorin Date: 2010-03-21T07:16:09+09:00 Subject: ops.epo.org hacks (was: Wsdl - Webservice Client) --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Mar 17, 2010 at 12:31:57AM +0900, Axel Fuchs wrote: > Brian, thank you very much for your help. This is really > unnecessarily complex. The only reason I am interested in SOAP > is so that I can access the patent data information from the > European Patent Office (see my other post). I've posted some code on their forum: http://forums.epo.org/open-patent-services-and-publication-server-web-service/topic898.html The attached copies are slightly more updated. The code doesn't use anything but handmade XML processing since soap4r couldn't cope with WSDL2 or whatever new and improved spec version EPO has migrated to (espacenet was fine), and time was pretty short to wrestle with wso2.org first. I did run it last December, still worked back then. -- ---- WBR, Michael Shigorin ------ Linux.Kiev http://www.linux.kiev.ua/ --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="ops.rb" #!/usr/bin/ruby require 'net/http' require 'rexml/document' module OPS class SoapReq < REXML::Element DEBUG = false #DEBUG = true attr_reader :xml # FIXME: should be unneeded @@xpath_prefix = "SOAP-ENV:Body/ops:world-patent-data" def initialize(action, docnumber, kind = "%%") @query = <<-END_QUERY #{docnumber} #{kind} END_QUERY @path = "/soap-services/#{action}" @headers = { "SOAPAction" => action, "Content-Type" => "text/xml; charset=utf-8" } puts "[ops.rb] SOAP request:", @query if DEBUG begin @http = Net::HTTP.new("ops.epo.org") @response, @data = @http.post(@path, @query, @headers) puts "[ops.rb] HTTP response: #{@response}" if DEBUG rescue => net_error puts "** [ops.rb] trouble while querying OPS: #{net_error}" end @xml = REXML::Document.new(@data).root end end class Biblio < SoapReq attr_reader :kind @@xpath1 = "#{@@xpath_prefix}/exchange-documents/exchange-document" @@xpath2 = "#{@@xpath_prefix}/exchange-documents/exchange-document/bibliographic-data" def initialize(docnumber) # that req handler does accept wildcards super("biblio-retrieval", docnumber, "%%") @kind = @xml.elements[@@xpath1].attributes["kind"] puts "[ops.rb] Biblio: #{@xml.elements[@@xpath2].inspect}" if DEBUG @xml = @xml.elements[@@xpath2] end end class Equiv < SoapReq @@xpath = "#{@@xpath_prefix}/ops:equivalents-inquiry" def initialize(docnumber, kind) # that req handler does NOT accept wildcards super("equivalents-inquiry", docnumber, kind) puts "[ops.rb] Equivalents: #{@xml.elements[@@xpath].inspect}" if DEBUG @xml = @xml.elements[@@xpath] end end class Family < SoapReq @@xpath = "#{@@xpath_prefix}/ops:patent-family" def initialize(docnumber) # that req handler only accepts empty super("family-retrieval", docnumber, "") puts "[ops.rb] Family: #{@xml.elements[@@xpath].inspect}" if DEBUG @xml = @xml.elements[@@xpath] end end end --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="patent.rb" #!/usr/bin/env ruby require 'rexml/document' require 'ops.rb' module OPS class Reference attr_reader :docnumber # :date is special def initialize(docnumber, date) @docnumber = docnumber @date = date end def date "#{@date[0..3]}-#{@date[4..5]}-#{@date[6..7]}" end def to_s "#{@docnumber} #{@date}" end alias inspect to_s end class PublicationReference < Reference attr_reader :country, :number, :kind @@xpath = "publication-reference[@data-format='epodoc']/document-id" def initialize(xml) e = xml.elements[@@xpath] @docnumber = e.elements["doc-number"].text @country = @docnumber[0..1] @number = @docnumber[2..-1] @date = e.elements["date"].text # FIXME: was _needed_ for table B.6.1, revisit this @kind = xml.elements["publication-reference[@data-format='docdb']/document-id/kind"].text self end def to_s "#{@docnumber} (#{kind}) -- #{self.date}" end alias inspect to_s end class ApplicationReference < Reference @@xpath = "application-reference[@data-format='epodoc']/document-id" def initialize(xml) e = xml.elements[@@xpath] @docnumber = e.elements["doc-number"].text @date = e.elements["date"].text self end end class PriorityClaim < Reference; end class PriorityClaims < Array @@xpath = "priority-claims/priority-claim[@data-format='epodoc']/document-id" def initialize(xml) xml.elements.each(@@xpath) { |e| docnumber = e.elements["doc-number"].text date = e.elements["date"].text self.push PriorityClaim.new(docnumber, date) } self end end class ClassificationIPCR < String def initialize(text) self << text.delete(" ").chop.chop end end class Classifications < Array @@xpath = "classifications-ipcr/classification-ipcr/text" def initialize(xml) xml.elements.each(@@xpath) { |e| self.push ClassificationIPCR.new(e.text) } self end end class Applicants < Array @@xpath = "parties/applicants/applicant[@data-format='epodoc']/applicant-name/name" def initialize(xml) xml.elements.each(@@xpath) { |e| self.push e.text } self end end class Title < String # lang="en" def initialize(xml) # FIXME: what if several translations exist? [probably w/o en] begin self << xml.elements["invention-title[@lang='en']"].text rescue NoMethodError self << xml.elements["invention-title"].text end end end class Equivalent < String # not < Reference since only docnumber def initialize(xml) self << xml.elements["doc-number"].text end end class Equivalents < Array @@xpath = "ops:inquiry-result/publication-reference[@data-format='epodoc']/document-id" def initialize(xml) begin xml.elements.each(@@xpath) { |e| self.push Equivalent.new(e) } rescue NoMethodError end self end end class Patent attr_reader :docnumber, :pubref, :appref, :classes attr_reader :prioclaims, :applicants, :title, :kind attr_reader :equivs def initialize(docnumber) @docnumber = docnumber # NB: after replacing biblio with biblio+xml, # the Patent lost the ability to be inspected (?!?) @biblio = OPS::Biblio.new(@docnumber) @kind = @biblio.kind # it's an attribute, not sub-element # FIXME: currently we don't need equivalents, maybe separate them? #@equivs = Equivalents.new(OPS::Equiv.new(@docnumber, @kind).xml) @equivs = [] @xml = @biblio.xml @pubref = PublicationReference.new(@xml) @appref = ApplicationReference.new(@xml) @classes = Classifications.new(@xml) @prioclaims = PriorityClaims.new(@xml) @applicants = Applicants.new(@xml) @title = Title.new(@xml) end def inspect "No. #{@docnumber} (#{@kind}) \"#{@title}\" #{@applicants}; Appl. No #{@appref}; Pub. No #{@pubref}; Pri. No #{@prioclaims}; Cls. #{@classes}; Eq. #{@equivs}" end end end --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="family.rb" #!/usr/bin/env ruby require 'rexml/document' require 'patent.rb' require 'ops.rb' module OPS class FamilyPublications < Array @@xpath = "ops:family-member" def initialize(xml) xml.elements.each(@@xpath) { |e| self.push PublicationReference.new(e) } self end end class PatentFamily attr_reader :docnumber, :fampubs def initialize(docnumber) @docnumber = docnumber @fampubs = FamilyPublications.new(OPS::Family.new(@docnumber).xml) end def inspect "No. #{@docnumber}'s family: #{@fampubs}" end end end --qMm9M+Fa2AknHoGS--