source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/parser.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 6.0 KB
Line 
1# SOAP4R - SOAP XML Instance Parser library.
2# Copyright (C) 2001, 2003 NAKAMURA, Hiroshi <[email protected]>.
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
9require 'xsd/ns'
10require 'xsd/xmlparser'
11require 'soap/soap'
12require 'soap/baseData'
13require 'soap/encodingstyle/handler'
14
15
16module SOAP
17
18
19class Parser
20 include SOAP
21
22 class ParseError < Error; end
23 class FormatDecodeError < ParseError; end
24 class UnexpectedElementError < ParseError; end
25
26private
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
61public
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
155private
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
248end
249
250
251end
Note: See TracBrowser for help on using the repository browser.