~ubuntu-branches/ubuntu/intrepid/ruby1.8/intrepid-updates

« back to all changes in this revision

Viewing changes to lib/soap/parser.rb

  • Committer: Bazaar Package Importer
  • Author(s): akira yamada
  • Date: 2007-03-13 22:11:58 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070313221158-h3oql37brlaf2go2
Tags: 1.8.6-1
* new upstream version, 1.8.6.
* libruby1.8 conflicts with libopenssl-ruby1.8 (< 1.8.6) (closes: #410018)
* changed packaging style to cdbs from dbs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# SOAP4R - SOAP XML Instance Parser library.
 
2
# Copyright (C) 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
 
3
 
 
4
# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
 
5
# redistribute it and/or modify it under the same terms of Ruby's license;
 
6
# either the dual license version in 2003, or any later version.
 
7
 
 
8
 
 
9
require 'xsd/ns'
 
10
require 'xsd/xmlparser'
 
11
require 'soap/soap'
 
12
require 'soap/baseData'
 
13
require 'soap/encodingstyle/handler'
 
14
 
 
15
 
 
16
module SOAP
 
17
 
 
18
 
 
19
class Parser
 
20
  include SOAP
 
21
 
 
22
  class ParseError < Error; end
 
23
  class FormatDecodeError < ParseError; end
 
24
  class UnexpectedElementError < ParseError; end
 
25
 
 
26
private
 
27
 
 
28
  class ParseFrame
 
29
    attr_reader :node
 
30
    attr_reader :name
 
31
    attr_reader :ns, :encodingstyle
 
32
 
 
33
    class NodeContainer
 
34
      def initialize(node)
 
35
        @node = node
 
36
      end
 
37
 
 
38
      def node
 
39
        @node
 
40
      end
 
41
 
 
42
      def replace_node(node)
 
43
        @node = node
 
44
      end
 
45
    end
 
46
 
 
47
  public
 
48
 
 
49
    def initialize(ns, name, node, encodingstyle)
 
50
      @ns = ns
 
51
      @name = name
 
52
      self.node = node
 
53
      @encodingstyle = encodingstyle
 
54
    end
 
55
 
 
56
    def node=(node)
 
57
      @node = NodeContainer.new(node)
 
58
    end
 
59
  end
 
60
 
 
61
public
 
62
 
 
63
  attr_accessor :envelopenamespace
 
64
  attr_accessor :default_encodingstyle
 
65
  attr_accessor :decode_typemap
 
66
  attr_accessor :allow_unqualified_element
 
67
 
 
68
  def initialize(opt = {})
 
69
    @opt = opt
 
70
    @parser = XSD::XMLParser.create_parser(self, opt)
 
71
    @parsestack = nil
 
72
    @lastnode = nil
 
73
    @handlers = {}
 
74
    @envelopenamespace = opt[:envelopenamespace] || EnvelopeNamespace
 
75
    @default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
 
76
    @decode_typemap = opt[:decode_typemap] || nil
 
77
    @allow_unqualified_element = opt[:allow_unqualified_element] || false
 
78
  end
 
79
 
 
80
  def charset
 
81
    @parser.charset
 
82
  end
 
83
 
 
84
  def parse(string_or_readable)
 
85
    @parsestack = []
 
86
    @lastnode = nil
 
87
 
 
88
    @handlers.each do |uri, handler|
 
89
      handler.decode_prologue
 
90
    end
 
91
 
 
92
    @parser.do_parse(string_or_readable)
 
93
 
 
94
    unless @parsestack.empty?
 
95
      raise FormatDecodeError.new("Unbalanced tag in XML.")
 
96
    end
 
97
 
 
98
    @handlers.each do |uri, handler|
 
99
      handler.decode_epilogue
 
100
    end
 
101
 
 
102
    @lastnode
 
103
  end
 
104
 
 
105
  def start_element(name, attrs)
 
106
    lastframe = @parsestack.last
 
107
    ns = parent = parent_encodingstyle = nil
 
108
    if lastframe
 
109
      ns = lastframe.ns.clone_ns
 
110
      parent = lastframe.node
 
111
      parent_encodingstyle = lastframe.encodingstyle
 
112
    else
 
113
      ns = XSD::NS.new
 
114
      parent = ParseFrame::NodeContainer.new(nil)
 
115
      parent_encodingstyle = nil
 
116
    end
 
117
 
 
118
    attrs = XSD::XMLParser.filter_ns(ns, attrs)
 
119
    encodingstyle = find_encodingstyle(ns, attrs)
 
120
 
 
121
    # Children's encodingstyle is derived from its parent.
 
122
    if encodingstyle.nil?
 
123
      if parent.node.is_a?(SOAPHeader)
 
124
        encodingstyle = LiteralNamespace
 
125
      else
 
126
        encodingstyle = parent_encodingstyle || @default_encodingstyle
 
127
      end
 
128
    end
 
129
 
 
130
    node = decode_tag(ns, name, attrs, parent, encodingstyle)
 
131
 
 
132
    @parsestack << ParseFrame.new(ns, name, node, encodingstyle)
 
133
  end
 
134
 
 
135
  def characters(text)
 
136
    lastframe = @parsestack.last
 
137
    if lastframe
 
138
      # Need not to be cloned because character does not have attr.
 
139
      decode_text(lastframe.ns, text, lastframe.encodingstyle)
 
140
    else
 
141
      # Ignore Text outside of SOAP Envelope.
 
142
      p text if $DEBUG
 
143
    end
 
144
  end
 
145
 
 
146
  def end_element(name)
 
147
    lastframe = @parsestack.pop
 
148
    unless name == lastframe.name
 
149
      raise UnexpectedElementError.new("Closing element name '#{ name }' does not match with opening element '#{ lastframe.name }'.")
 
150
    end
 
151
    decode_tag_end(lastframe.ns, lastframe.node, lastframe.encodingstyle)
 
152
    @lastnode = lastframe.node.node
 
153
  end
 
154
 
 
155
private
 
156
 
 
157
  def find_encodingstyle(ns, attrs)
 
158
    attrs.each do |key, value|
 
159
      if (ns.compare(@envelopenamespace, AttrEncodingStyle, key))
 
160
        return value
 
161
      end
 
162
    end
 
163
    nil
 
164
  end
 
165
 
 
166
  def decode_tag(ns, name, attrs, parent, encodingstyle)
 
167
    ele = ns.parse(name)
 
168
 
 
169
    # Envelope based parsing.
 
170
    if ((ele.namespace == @envelopenamespace) ||
 
171
        (@allow_unqualified_element && ele.namespace.nil?))
 
172
      o = decode_soap_envelope(ns, ele, attrs, parent)
 
173
      return o if o
 
174
    end
 
175
 
 
176
    # Encoding based parsing.
 
177
    handler = find_handler(encodingstyle)
 
178
    if handler
 
179
      return handler.decode_tag(ns, ele, attrs, parent)
 
180
    else
 
181
      raise FormatDecodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
 
182
    end
 
183
  end
 
184
 
 
185
  def decode_tag_end(ns, node, encodingstyle)
 
186
    return unless encodingstyle
 
187
 
 
188
    handler = find_handler(encodingstyle)
 
189
    if handler
 
190
      return handler.decode_tag_end(ns, node)
 
191
    else
 
192
      raise FormatDecodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
 
193
    end
 
194
  end
 
195
 
 
196
  def decode_text(ns, text, encodingstyle)
 
197
    handler = find_handler(encodingstyle)
 
198
 
 
199
    if handler
 
200
      handler.decode_text(ns, text)
 
201
    else
 
202
      # How should I do?
 
203
    end
 
204
  end
 
205
 
 
206
  def decode_soap_envelope(ns, ele, attrs, parent)
 
207
    o = nil
 
208
    if ele.name == EleEnvelope
 
209
      o = SOAPEnvelope.new
 
210
      if ext = @opt[:external_content]
 
211
        ext.each do |k, v|
 
212
          o.external_content[k] = v
 
213
        end
 
214
      end
 
215
    elsif ele.name == EleHeader
 
216
      unless parent.node.is_a?(SOAPEnvelope)
 
217
        raise FormatDecodeError.new("Header should be a child of Envelope.")
 
218
      end
 
219
      o = SOAPHeader.new
 
220
      parent.node.header = o
 
221
    elsif ele.name == EleBody
 
222
      unless parent.node.is_a?(SOAPEnvelope)
 
223
        raise FormatDecodeError.new("Body should be a child of Envelope.")
 
224
      end
 
225
      o = SOAPBody.new
 
226
      parent.node.body = o
 
227
    elsif ele.name == EleFault
 
228
      unless parent.node.is_a?(SOAPBody)
 
229
        raise FormatDecodeError.new("Fault should be a child of Body.")
 
230
      end
 
231
      o = SOAPFault.new
 
232
      parent.node.fault = o
 
233
    end
 
234
    o
 
235
  end
 
236
 
 
237
  def find_handler(encodingstyle)
 
238
    unless @handlers.key?(encodingstyle)
 
239
      handler_factory = SOAP::EncodingStyle::Handler.handler(encodingstyle) ||
 
240
        SOAP::EncodingStyle::Handler.handler(EncodingNamespace)
 
241
      handler = handler_factory.new(@parser.charset)
 
242
      handler.decode_typemap = @decode_typemap
 
243
      handler.decode_prologue
 
244
      @handlers[encodingstyle] = handler
 
245
    end
 
246
    @handlers[encodingstyle]
 
247
  end
 
248
end
 
249
 
 
250
 
 
251
end