| Class | SOAP::SOAPGenerator |
| In: |
lib/soap/generator.rb
|
| Parent: | Object |
CAUTION: MT-unsafe
| EncodeMap | = | { '&' => '&', '<' => '<', '>' => '>', '"' => '"', '\'' => ''', "\r" => '
' |
| EncodeCharRegexp | = | Regexp.new("[#{EncodeMap.keys.join}]") |
| charset | [RW] | |
| default_encodingstyle | [RW] | |
| generate_explicit_type | [RW] | |
| use_numeric_character_reference | [RW] |
# File lib/soap/generator.rb, line 225
225: def self.assign_ns(attrs, ns, namespace, tag = nil)
226: if namespace.nil?
227: raise FormatEncodeError.new("empty namespace")
228: end
229: unless ns.assigned?(namespace)
230: tag = ns.assign(namespace, tag)
231: if tag == ''
232: attr = 'xmlns'
233: else
234: attr = "xmlns:#{tag}"
235: end
236: attrs[attr] = namespace
237: end
238: end
# File lib/soap/generator.rb, line 33
33: def initialize(opt = {})
34: @reftarget = nil
35: @handlers = {}
36: @charset = opt[:charset] || XSD::Charset.xml_encoding_label
37: @default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
38: @generate_explicit_type =
39: opt.key?(:generate_explicit_type) ? opt[:generate_explicit_type] : true
40: @elementformdefault = opt[:elementformdefault]
41: @attributeformdefault = opt[:attributeformdefault]
42: @use_numeric_character_reference = opt[:use_numeric_character_reference]
43: @indentstr = opt[:no_indent] ? '' : ' '
44: @buf = @indent = @curr = nil
45: end
# File lib/soap/generator.rb, line 97
97: def add_reftarget(name, node)
98: unless @reftarget
99: raise FormatEncodeError.new("Reftarget is not defined.")
100: end
101: @reftarget.add(name, node)
102: end
# File lib/soap/generator.rb, line 209
209: def element_local?(element)
210: element.elename.namespace.nil?
211: end
# File lib/soap/generator.rb, line 213
213: def element_qualified?(element)
214: if element.respond_to?(:qualified)
215: if element.qualified.nil?
216: @elementformdefault
217: else
218: element.qualified
219: end
220: else
221: @elementformdefault
222: end
223: end
# File lib/soap/generator.rb, line 104
104: def encode_child(ns, child, parent)
105: indent_backup, @indent = @indent, @indent + @indentstr
106: encode_data(ns.clone_ns, child, parent)
107: @indent = indent_backup
108: end
# File lib/soap/generator.rb, line 68
68: def encode_data(ns, obj, parent)
69: if obj.is_a?(SOAPEnvelopeElement)
70: encode_element(ns, obj, parent)
71: return
72: end
73: if @reftarget && !obj.precedents.empty?
74: add_reftarget(obj.elename.name, obj)
75: ref = SOAPReference.new(obj)
76: ref.elename = ref.elename.dup_name(obj.elename.name)
77: obj.precedents.clear # Avoid cyclic delay.
78: obj.encodingstyle = parent.encodingstyle
79: # SOAPReference is encoded here.
80: obj = ref
81: end
82: encodingstyle = obj.encodingstyle
83: # Children's encodingstyle is derived from its parent.
84: encodingstyle ||= parent.encodingstyle if parent
85: obj.encodingstyle = encodingstyle
86: handler = find_handler(encodingstyle || @default_encodingstyle)
87: unless handler
88: raise FormatEncodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
89: end
90: if !obj.elename.name
91: raise FormatEncodeError.new("Element name not defined: #{ obj }.")
92: end
93: handler.encode_data(self, ns, obj, parent)
94: handler.encode_data_end(self, ns, obj, parent)
95: end
# File lib/soap/generator.rb, line 110
110: def encode_element(ns, obj, parent)
111: attrs = {}
112: if obj.is_a?(SOAPBody)
113: @reftarget = obj
114: obj.encode(self, ns, attrs) do |child|
115: indent_backup, @indent = @indent, @indent + @indentstr
116: encode_data(ns.clone_ns, child, obj)
117: @indent = indent_backup
118: end
119: @reftarget = nil
120: else
121: if obj.is_a?(SOAPEnvelope)
122: # xsi:nil="true" can appear even if dumping without explicit type.
123: SOAPGenerator.assign_ns(attrs, ns,
124: XSD::InstanceNamespace, XSINamespaceTag)
125: if @generate_explicit_type
126: SOAPGenerator.assign_ns(attrs, ns, XSD::Namespace, XSDNamespaceTag)
127: end
128: end
129: obj.encode(self, ns, attrs) do |child|
130: indent_backup, @indent = @indent, @indent + @indentstr
131: encode_data(ns.clone_ns, child, obj)
132: @indent = indent_backup
133: end
134: end
135: end
# File lib/soap/generator.rb, line 137
137: def encode_name(ns, data, attrs)
138: if element_local?(data)
139: data.elename.name
140: else
141: if element_qualified?(data)
142: SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace, '')
143: else
144: SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
145: end
146: ns.name(data.elename)
147: end
148: end
# File lib/soap/generator.rb, line 150
150: def encode_name_end(ns, data)
151: if element_local?(data)
152: data.elename.name
153: else
154: ns.name(data.elename)
155: end
156: end
# File lib/soap/generator.rb, line 194
194: def encode_string(str)
195: if @use_numeric_character_reference and !XSD::Charset.is_us_ascii(str)
196: str.gsub!(EncodeCharRegexp) { |c| EncodeMap[c] }
197: @buf << str.unpack("U*").collect { |c|
198: if c == 0x9 or c == 0xa or c == 0xd or (c >= 0x20 and c <= 0x7f)
199: c.chr
200: else
201: sprintf("&#x%x;", c)
202: end
203: }.join
204: else
205: @buf << str.gsub(EncodeCharRegexp) { |c| EncodeMap[c] }
206: end
207: end
# File lib/soap/generator.rb, line 158
158: def encode_tag(elename, attrs = nil)
159: if !attrs or attrs.empty?
160: @buf << "\n#{ @indent }<#{ elename }>"
161: elsif attrs.size == 1
162: key, value = attrs.shift
163: @buf << %Q[\n#{ @indent }<#{ elename } #{ key }="#{ value }">]
164: else
165: @buf << "\n#{ @indent }<#{ elename } " <<
166: attrs.collect { |key, value|
167: %Q[#{ key }="#{ value }"]
168: }.join("\n#{ @indent }#{ @indentstr * 2 }") <<
169: '>'
170: end
171: end
# File lib/soap/generator.rb, line 173
173: def encode_tag_end(elename, cr = nil)
174: if cr
175: @buf << "\n#{ @indent }</#{ elename }>"
176: else
177: @buf << "</#{ elename }>"
178: end
179: end
# File lib/soap/generator.rb, line 47
47: def generate(obj, io = nil)
48: @buf = io || ''
49: @indent = ''
50:
51: prologue
52: @handlers.each do |uri, handler|
53: handler.encode_prologue
54: end
55:
56: ns = XSD::NS.new
57: @buf << xmldecl
58: encode_data(ns, obj, nil)
59:
60: @handlers.each do |uri, handler|
61: handler.encode_epilogue
62: end
63: epilogue
64:
65: @buf
66: end
# File lib/soap/generator.rb, line 248
248: def find_handler(encodingstyle)
249: unless @handlers.key?(encodingstyle)
250: handler = SOAP::EncodingStyle::Handler.handler(encodingstyle).new(@charset)
251: handler.generate_explicit_type = @generate_explicit_type
252: handler.encode_prologue
253: @handlers[encodingstyle] = handler
254: end
255: @handlers[encodingstyle]
256: end