cheri 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README +387 -15
- data/lib/cheri/awt.rb +4 -2
- data/lib/cheri/builder.rb +1 -0
- data/lib/cheri/builder/awt/main.rb +1 -1
- data/lib/cheri/builder/base.rb +1 -321
- data/lib/cheri/builder/config.rb +6 -2
- data/lib/cheri/builder/context.rb +103 -26
- data/lib/cheri/builder/generator.rb +38 -32
- data/lib/cheri/builder/html/element.rb +106 -16
- data/lib/cheri/builder/html/main.rb +125 -19
- data/lib/cheri/builder/html/types.rb +12 -2
- data/lib/cheri/builder/main.rb +200 -7
- data/lib/cheri/builder/markup.rb +608 -0
- data/lib/cheri/builder/swing/main.rb +2 -2
- data/lib/cheri/builder/xml/connecter.rb +11 -0
- data/lib/cheri/builder/xml/element.rb +141 -22
- data/lib/cheri/builder/xml/main.rb +188 -32
- data/lib/cheri/builder/xml/types.rb +5 -0
- data/lib/cheri/cheri.rb +1 -1
- data/lib/cheri/explorer.rb +4 -2
- data/lib/cheri/explorer/explorer.rb +4 -2
- data/lib/cheri/java/builder/main.rb +32 -11
- data/lib/cheri/jruby.rb +4 -2
- data/lib/cheri/jruby/explorer.rb +4 -2
- data/lib/cheri/swing.rb +4 -2
- metadata +3 -2
@@ -87,7 +87,7 @@ end #self
|
|
87
87
|
# Duplicating this here rather than including Cheri::AWT. (See note re: performance)
|
88
88
|
#++
|
89
89
|
def awt(*r,&k)
|
90
|
-
if
|
90
|
+
if ctx = __cheri_ctx
|
91
91
|
if k
|
92
92
|
AWTFrame.new(ctx,*r,&k).run
|
93
93
|
else
|
@@ -101,7 +101,7 @@ end #self
|
|
101
101
|
# swing([*args] [, &block]) -> SwingProxy if no block given, else result of block
|
102
102
|
#
|
103
103
|
def swing(*r,&k)
|
104
|
-
if
|
104
|
+
if ctx = __cheri_ctx
|
105
105
|
if k
|
106
106
|
if ctx.empty? && (c = ctx.client).kind_of?(RPC) || c.kind_of?(JComp)
|
107
107
|
ctx.fsend(CheriYieldFactory,:cheri_yield,c,&k)
|
@@ -36,6 +36,17 @@ XmlConnecter = Cheri::Builder::TypeConnecter.new do
|
|
36
36
|
connect XmlElement
|
37
37
|
end
|
38
38
|
|
39
|
+
type TextElem do
|
40
|
+
connect XmlElement
|
41
|
+
connect Cheri::Builder::Content
|
42
|
+
connect Object
|
43
|
+
end
|
44
|
+
|
45
|
+
type Namespace do
|
46
|
+
connect XmlElement do |namespace,elem|
|
47
|
+
elem.ns ||= namespace.__prefix__
|
48
|
+
end
|
49
|
+
end
|
39
50
|
end #XmlConnecter
|
40
51
|
|
41
52
|
end #Xml
|
@@ -32,18 +32,18 @@ end #XmlElement
|
|
32
32
|
|
33
33
|
# Included by all Cheri::Xml builders
|
34
34
|
module XmlBuilder
|
35
|
-
|
35
|
+
TCE = ' />'.freeze #:nodoc:
|
36
36
|
|
37
37
|
def empty_s(str='')
|
38
|
-
str <<
|
38
|
+
str << TCE
|
39
39
|
end
|
40
40
|
|
41
41
|
def empty_io(ios)
|
42
|
-
ios <<
|
42
|
+
ios << TCE
|
43
43
|
end
|
44
44
|
|
45
45
|
def esc(inp,out=nil)
|
46
|
-
if @
|
46
|
+
if @opt[:esc] && (cs = Charsets.charset(inp))
|
47
47
|
cs.xlat(inp,(out ||= ''))
|
48
48
|
out
|
49
49
|
elsif out
|
@@ -58,10 +58,26 @@ class Elem
|
|
58
58
|
include Cheri::Builder::MarkupBuilder
|
59
59
|
include XmlBuilder
|
60
60
|
include XmlElement
|
61
|
+
|
62
|
+
def initialize(ctx,*r,&k)
|
63
|
+
opt = @opt = ctx[:xml_opts] || {}
|
64
|
+
@fmt = true if opt[:format]
|
65
|
+
@amap = opt[:attr] if opt[:attr]
|
66
|
+
super
|
67
|
+
end
|
61
68
|
|
62
69
|
def mod
|
63
70
|
Cheri::Xml
|
64
71
|
end
|
72
|
+
|
73
|
+
def margin
|
74
|
+
@mrg || @opt[:margin] || @ctx[:margin] || 0
|
75
|
+
end
|
76
|
+
|
77
|
+
def indent
|
78
|
+
@idt || @opt[:indent] || @ctx[:indent] || 0
|
79
|
+
end
|
80
|
+
|
65
81
|
end
|
66
82
|
|
67
83
|
class EmptyElem
|
@@ -69,40 +85,53 @@ class EmptyElem
|
|
69
85
|
include XmlBuilder
|
70
86
|
include XmlElement
|
71
87
|
|
88
|
+
def initialize(ctx,*r,&k)
|
89
|
+
opt = @opt = ctx[:xml_opts] || {}
|
90
|
+
@fmt = true if opt[:format]
|
91
|
+
@amap = opt[:attr] if opt[:attr]
|
92
|
+
super
|
93
|
+
end
|
94
|
+
|
72
95
|
def mod
|
73
96
|
Cheri::Xml
|
74
97
|
end
|
75
98
|
|
76
|
-
def
|
99
|
+
def add?(value)
|
77
100
|
raise XmlException,"content not allowed for empty element #{@sym}: #{value}"
|
78
101
|
end
|
79
|
-
end
|
80
102
|
|
103
|
+
def margin
|
104
|
+
@mrg || @opt[:margin] || @ctx[:margin] || 0
|
105
|
+
end
|
106
|
+
|
107
|
+
def indent
|
108
|
+
@idt || @opt[:indent] || @ctx[:indent] || 0
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
81
112
|
|
82
113
|
class TextElem
|
83
|
-
include Cheri::Builder::
|
84
|
-
include Cheri::Builder::Content
|
85
|
-
include Cheri::Builder::ContentArgs
|
114
|
+
include Cheri::Builder::MarkupLikeBuilder
|
86
115
|
include XmlBuilder
|
87
116
|
|
88
|
-
def
|
89
|
-
|
117
|
+
def initialize(ctx,*r,&k)
|
118
|
+
@opt = ctx[:xml_opts] || {}
|
119
|
+
super
|
90
120
|
end
|
91
121
|
|
92
|
-
def
|
93
|
-
|
122
|
+
def set?(n,v)
|
123
|
+
raise XmlException,"attribute not allowed for text element #{@sym}: #{n}=#{v}"
|
94
124
|
end
|
125
|
+
private :set?
|
95
126
|
|
96
|
-
def
|
97
|
-
|
98
|
-
add(value) if String === value
|
99
|
-
#add(value) if value && !(Appendable === value || BaseProxy === value)
|
100
|
-
self
|
127
|
+
def mod
|
128
|
+
Cheri::Xml
|
101
129
|
end
|
102
130
|
|
103
131
|
# Appends content to +str+, or to an empty string if +str+ is omitted.
|
104
132
|
# Returns the result.
|
105
133
|
def to_s(str='')
|
134
|
+
return to_io(str) unless String === str
|
106
135
|
@cont.each do |c|
|
107
136
|
if String === c
|
108
137
|
esc(c,str)
|
@@ -127,6 +156,7 @@ class TextElem
|
|
127
156
|
|
128
157
|
end
|
129
158
|
|
159
|
+
# Like TextElem, but always escapes values, regardless of :esc setting
|
130
160
|
class EscElem < TextElem
|
131
161
|
|
132
162
|
def esc(inp,out=nil)
|
@@ -142,14 +172,54 @@ class EscElem < TextElem
|
|
142
172
|
|
143
173
|
end
|
144
174
|
|
175
|
+
class CommentElem
|
176
|
+
include Cheri::Builder::CommentBuilder
|
177
|
+
include XmlBuilder
|
178
|
+
include XmlElement
|
179
|
+
# :stopdoc:
|
180
|
+
CO = '<!-- '.freeze
|
181
|
+
CC = ' -->'.freeze
|
182
|
+
CCLF = " -->\n".freeze
|
183
|
+
# :startdoc:
|
184
|
+
def initialize(ctx,*r,&k)
|
185
|
+
opt = @opt = ctx[:xml_opts] || {}
|
186
|
+
@fmt = true if opt[:format]
|
187
|
+
super
|
188
|
+
end
|
189
|
+
|
190
|
+
def set?(n,v)
|
191
|
+
raise XmlException,"attribute not allowed for comment #{@sym}: #{n}=#{v}"
|
192
|
+
end
|
193
|
+
private :set?
|
194
|
+
|
195
|
+
def mod
|
196
|
+
Cheri::Xml
|
197
|
+
end
|
198
|
+
|
199
|
+
def margin
|
200
|
+
@mrg || @opt[:margin] || @ctx[:margin] || 0
|
201
|
+
end
|
202
|
+
|
203
|
+
def indent
|
204
|
+
@idt || @opt[:indent] || @ctx[:indent] || 0
|
205
|
+
end
|
206
|
+
|
207
|
+
end #CommentElem
|
208
|
+
|
145
209
|
# TODO: special handling for these:
|
146
210
|
|
147
211
|
class XmlRoot
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
include Cheri::Builder::
|
212
|
+
# :stopdoc:
|
213
|
+
XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>".freeze
|
214
|
+
# :startdoc:
|
215
|
+
include Cheri::Builder::MarkupBuilder
|
152
216
|
include XmlBuilder
|
217
|
+
|
218
|
+
def initialize(ctx,*r,&k)
|
219
|
+
opt = @opt = ctx[:xml_opts] || {}
|
220
|
+
@fmt = true if opt[:format]
|
221
|
+
super
|
222
|
+
end
|
153
223
|
|
154
224
|
def mod
|
155
225
|
Cheri::Xml
|
@@ -167,17 +237,29 @@ class XmlRoot
|
|
167
237
|
# Appends content to +str+ (or new String if +str+ is omitted). Returns the result.
|
168
238
|
def to_s(str='')
|
169
239
|
return to_io(str) unless String === str
|
240
|
+
str << ' ' * @opt[:margin] if @fmt && @opt[:margin]
|
170
241
|
str << XML
|
242
|
+
str << 10 if @fmt
|
171
243
|
cont_s(str)
|
172
244
|
str
|
173
245
|
end
|
174
246
|
|
175
247
|
# Appends content to +ios+. Returns the result.
|
176
248
|
def to_io(ios)
|
249
|
+
ios << ' ' * @opt[:margin] if @fmt && @opt[:margin]
|
177
250
|
ios << XML
|
251
|
+
ios << LF if @fmt
|
178
252
|
cont_io(ios)
|
179
253
|
ios
|
180
254
|
end
|
255
|
+
|
256
|
+
def format!
|
257
|
+
@fmt = true
|
258
|
+
end
|
259
|
+
|
260
|
+
def depth
|
261
|
+
-1
|
262
|
+
end
|
181
263
|
|
182
264
|
end
|
183
265
|
|
@@ -185,5 +267,42 @@ end
|
|
185
267
|
class ProcElem < Elem
|
186
268
|
end
|
187
269
|
|
270
|
+
class Namespace
|
271
|
+
alias_method :__methods__,:methods
|
272
|
+
keep = /^(__|<|>|=)|^(class|inspect|to_s)$|(\?|!|=)$/
|
273
|
+
instance_methods.each do |m|
|
274
|
+
undef_method m unless m =~ keep
|
275
|
+
end
|
276
|
+
|
277
|
+
def initialize(ctx,prefix,uri=nil)
|
278
|
+
@ctx = ctx
|
279
|
+
@pfx = prefix.to_sym
|
280
|
+
@uri = uri if uri
|
281
|
+
end
|
282
|
+
|
283
|
+
def __prefix__
|
284
|
+
@pfx
|
285
|
+
end
|
286
|
+
|
287
|
+
def __uri__
|
288
|
+
@uri
|
289
|
+
end
|
290
|
+
|
291
|
+
def mod
|
292
|
+
Cheri::Xml
|
293
|
+
end
|
294
|
+
private :mod
|
295
|
+
|
296
|
+
def method_missing(sym,*r,&k)
|
297
|
+
@ctx.nsend(mod,@pfx,sym,*r,&k)
|
298
|
+
end
|
299
|
+
private :method_missing
|
300
|
+
|
301
|
+
def inspect
|
302
|
+
"#<#{self.class}:instance>"
|
303
|
+
end
|
304
|
+
|
305
|
+
end #Namespace
|
306
|
+
|
188
307
|
end #Xml
|
189
308
|
end #Cheri
|
@@ -41,7 +41,7 @@ class << self
|
|
41
41
|
|
42
42
|
def connecter
|
43
43
|
XmlConnecter
|
44
|
-
end
|
44
|
+
end
|
45
45
|
|
46
46
|
end #self
|
47
47
|
|
@@ -51,33 +51,170 @@ end #self
|
|
51
51
|
# xml([*args] [, &block]) -> XmlProxy if no block given, else result of block
|
52
52
|
#
|
53
53
|
def xml(*r,&k)
|
54
|
-
if
|
54
|
+
if ctx = __cheri_ctx
|
55
|
+
unless copts = ctx[:xml_opts]
|
56
|
+
iopts = ctx.ictx[:xml_opts] ||= XmlOptions.new
|
57
|
+
copts = ctx[:xml_opts] = XmlOptions.new(iopts)
|
58
|
+
end
|
55
59
|
if k
|
56
60
|
if ctx.tos(XmlBuilder)
|
57
61
|
XmlFrame.new(ctx,*r,&k).run
|
58
62
|
else
|
59
|
-
|
63
|
+
copts.ingest_args(*r) unless r.empty?
|
64
|
+
ctx.msend(Cheri::Xml,:xml,&k)
|
60
65
|
end
|
61
66
|
else
|
67
|
+
copts.ingest_args(*r) unless r.empty?
|
62
68
|
ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
|
63
69
|
end
|
64
70
|
end
|
65
71
|
end
|
66
72
|
private :xml
|
67
|
-
|
68
|
-
|
73
|
+
|
69
74
|
module XmlFactory
|
70
75
|
def self.builder(ctx,sym,*r,&k)
|
76
|
+
opts = ctx[:xml_opts] || {}
|
77
|
+
if ((als = opts[:alias]) && (asym = als[sym])) || (asym = Aliases[sym])
|
78
|
+
sym = asym
|
79
|
+
end
|
71
80
|
if (clazz = Types[sym])
|
72
81
|
clazz.new(ctx,sym,*r,&k)
|
73
|
-
elsif
|
82
|
+
elsif :no_ns == sym || ((hns = opts[:ns]) && hns[sym])
|
83
|
+
ns = (ctx[:xml_ns] ||= {})[sym] ||= Namespace.new(ctx,sym)
|
84
|
+
NamespaceBuilder.new(ns,ctx,sym,*r,&k)
|
85
|
+
elsif opts[:any] || ((acc = opts[:accept]) && acc[sym])
|
74
86
|
Elem.new(ctx,sym,*r,&k)
|
75
87
|
else
|
76
|
-
nil
|
88
|
+
nil
|
77
89
|
end
|
78
90
|
end
|
79
91
|
end #XmlFactory
|
80
92
|
|
93
|
+
class XmlOptions < Cheri::Builder::BaseOptions
|
94
|
+
def validate(key,value)
|
95
|
+
raise Cheri.type_error(key,Symbol) unless Symbol === key
|
96
|
+
case key
|
97
|
+
when :any : validate_boolean_nil(value) || nil
|
98
|
+
when :esc : validate_boolean_nil(value) || nil
|
99
|
+
when :format : validate_boolean_nil(value) || nil
|
100
|
+
when :indent
|
101
|
+
unless Fixnum === value
|
102
|
+
if true == value
|
103
|
+
value = 2
|
104
|
+
elsif false == value || nil == value
|
105
|
+
value = nil
|
106
|
+
else
|
107
|
+
raise Cheri.type_error(value,Fixnum,TrueClass,FalseClass,NilClass)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
store(:format,true) if value
|
111
|
+
value
|
112
|
+
when :margin
|
113
|
+
unless Fixnum === value
|
114
|
+
if false == value || nil == value
|
115
|
+
value = nil
|
116
|
+
else
|
117
|
+
raise Cheri.type_error(value,Fixnum,FalseClass,NilClass)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
store(:format,true) if value
|
121
|
+
value
|
122
|
+
when :ns
|
123
|
+
value = value.to_sym if String === value
|
124
|
+
if Symbol === value
|
125
|
+
hns = self[:ns] || {}
|
126
|
+
hns[value] = true
|
127
|
+
hns
|
128
|
+
elsif Array === value
|
129
|
+
hns = self[:ns] || {}
|
130
|
+
value.each do |ns|
|
131
|
+
if String === ns
|
132
|
+
ns = ns.to_sym
|
133
|
+
else
|
134
|
+
validate_symbol(ns)
|
135
|
+
end
|
136
|
+
hns[ns] = true
|
137
|
+
end
|
138
|
+
warn "warning: empty array specified in xml :ns" if value.empty?
|
139
|
+
hns
|
140
|
+
elsif Hash === value
|
141
|
+
value.each_pair do |k,v|
|
142
|
+
validate_symbol(k)
|
143
|
+
validate_boolean_nil(v)
|
144
|
+
end
|
145
|
+
value
|
146
|
+
else
|
147
|
+
raise Cheri.type_error(value,Symbol,Array,Hash)
|
148
|
+
end
|
149
|
+
when :accept
|
150
|
+
value = value.to_sym if String === value
|
151
|
+
if Symbol === value
|
152
|
+
acc = self[:accept] || {}
|
153
|
+
acc[value] = true
|
154
|
+
acc
|
155
|
+
elsif Array === value
|
156
|
+
acc = self[:accept] || {}
|
157
|
+
value.each do |a|
|
158
|
+
if String === a
|
159
|
+
a = a.to_sym
|
160
|
+
else
|
161
|
+
validate_symbol(a)
|
162
|
+
end
|
163
|
+
acc[a] = true
|
164
|
+
end
|
165
|
+
warn "warning: empty array specified in xml :accept" if value.empty?
|
166
|
+
store(:any,false)
|
167
|
+
acc
|
168
|
+
elsif Hash === value
|
169
|
+
value.each_pair do |k,v|
|
170
|
+
validate_symbol(k)
|
171
|
+
validate_boolean_nil(v)
|
172
|
+
end
|
173
|
+
value
|
174
|
+
else
|
175
|
+
raise Cheri.type_error(value,Symbol,Array,Hash)
|
176
|
+
end
|
177
|
+
when :alias
|
178
|
+
if Array === value
|
179
|
+
raise ArgumentError,"odd number of values for :alias" if ((len = value.length) & 1) == 1
|
180
|
+
als = self[:alias] || {}
|
181
|
+
(len>>1).times do |i|
|
182
|
+
als[value[i*2].to_sym] = value[i*2+1].to_sym
|
183
|
+
end
|
184
|
+
als
|
185
|
+
elsif Hash === value
|
186
|
+
value.each_pair do |k,v|
|
187
|
+
validate_symbol(k)
|
188
|
+
validate_symbol(v)
|
189
|
+
end
|
190
|
+
value
|
191
|
+
else
|
192
|
+
raise Cheri.type_error(value,Array,Hash)
|
193
|
+
end
|
194
|
+
when :attr
|
195
|
+
if Array === value
|
196
|
+
raise ArgumentError,"odd number of values for :attr" if ((len = value.length) & 1) == 1
|
197
|
+
als = self[:attr] || {}
|
198
|
+
(len>>1).times do |i|
|
199
|
+
als[value[i*2].to_sym] = value[i*2+1].to_sym
|
200
|
+
end
|
201
|
+
als
|
202
|
+
elsif Hash === value
|
203
|
+
value.each_pair do |k,v|
|
204
|
+
validate_symbol(k)
|
205
|
+
validate_symbol(v)
|
206
|
+
end
|
207
|
+
value
|
208
|
+
else
|
209
|
+
raise Cheri.type_error(value,Array,Hash)
|
210
|
+
end
|
211
|
+
else
|
212
|
+
raise ArgumentError,"invalid xml option: #{key}"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end #XmlOptions
|
216
|
+
|
217
|
+
|
81
218
|
class XmlProxy < Cheri::Builder::BaseProxy
|
82
219
|
|
83
220
|
impl(Types.keys)
|
@@ -87,43 +224,62 @@ class XmlProxy < Cheri::Builder::BaseProxy
|
|
87
224
|
end
|
88
225
|
private :mod
|
89
226
|
|
90
|
-
def [](
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
elsif Hash === opts
|
98
|
-
@ctx[:xml_any] = opts[:any] != false if opts[:any] != nil
|
99
|
-
@ctx[:xml_esc] = opts[:esc] != false if opts[:esc] != nil
|
100
|
-
if (accept = opts[:accept])
|
101
|
-
raise Cheri.type_error(accept,Array) unless Array === accept
|
102
|
-
acc = {}
|
103
|
-
accept.each do |a|
|
104
|
-
raise Cheri.type_error(a,Symbol) unless Symbol === a
|
105
|
-
acc[a] = true
|
106
|
-
end
|
107
|
-
@ctx[:xml_accept] = acc
|
108
|
-
@ctx[:xml_any] = nil
|
109
|
-
end
|
110
|
-
else
|
111
|
-
raise Cheri.type_error(opts,Hash,Symbol)
|
112
|
-
end
|
227
|
+
def [](*args)
|
228
|
+
ictx = (ctx = @ctx).ictx
|
229
|
+
iopts = ictx[:xml_opts] ||= XmlOptions.new
|
230
|
+
iopts.ingest_args(*args)
|
231
|
+
copts = ctx[:xml_opts] ||= XmlOptions.new
|
232
|
+
copts.ingest_args(*args)
|
113
233
|
nil
|
114
234
|
end
|
115
235
|
|
116
236
|
end #XmlProxy
|
117
237
|
|
238
|
+
class NamespaceBuilder
|
239
|
+
include Cheri::Builder::Builder
|
240
|
+
def initialize(ns,*r,&k)
|
241
|
+
super(*r,&k)
|
242
|
+
@obj = ns
|
243
|
+
end
|
244
|
+
def child?
|
245
|
+
false
|
246
|
+
end
|
247
|
+
def parent?
|
248
|
+
false
|
249
|
+
end
|
250
|
+
def any?
|
251
|
+
true
|
252
|
+
end
|
253
|
+
def mod
|
254
|
+
Cheri::Xml
|
255
|
+
end
|
256
|
+
end #NamespaceBuilder
|
257
|
+
|
118
258
|
class XmlFrame
|
119
259
|
include Cheri::Builder::Frame
|
120
260
|
def initialize(ctx,*r,&k)
|
121
|
-
super
|
122
|
-
@obj = ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
|
261
|
+
super(ctx,&k)
|
262
|
+
@obj = ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
|
263
|
+
@args = r unless r.empty?
|
123
264
|
end
|
124
265
|
def mod
|
125
266
|
Cheri::Xml
|
126
267
|
end
|
268
|
+
def run
|
269
|
+
if blk = @blk
|
270
|
+
if args = @args
|
271
|
+
opts = (ctx = @ctx)[:xml_opts]
|
272
|
+
temp = XmlOptions.new(opts)
|
273
|
+
temp.ingest_args(*args)
|
274
|
+
ctx[:xml_opts] = temp
|
275
|
+
result = ctx.call(self,&blk)
|
276
|
+
ctx[:xml_opts] = opts
|
277
|
+
result
|
278
|
+
else
|
279
|
+
@ctx.call(self,&blk)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
127
283
|
end #XmlFrame
|
128
284
|
|
129
285
|
end #Xml
|