r4x 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY ADDED
File without changes
data/LICENSE ADDED
@@ -0,0 +1,168 @@
1
+ .
2
+
3
+ GNU LESSER GENERAL PUBLIC LICENSE
4
+ Version 3, 29 June 2007
5
+
6
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
7
+ Everyone is permitted to copy and distribute verbatim copies
8
+ of this license document, but changing it is not allowed.
9
+
10
+
11
+ This version of the GNU Lesser General Public License incorporates
12
+ the terms and conditions of version 3 of the GNU General Public
13
+ License, supplemented by the additional permissions listed below.
14
+
15
+ 0. Additional Definitions.
16
+
17
+ As used herein, "this License" refers to version 3 of the GNU Lesser
18
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
19
+ General Public License.
20
+
21
+ "The Library" refers to a covered work governed by this License,
22
+ other than an Application or a Combined Work as defined below.
23
+
24
+ An "Application" is any work that makes use of an interface provided
25
+ by the Library, but which is not otherwise based on the Library.
26
+ Defining a subclass of a class defined by the Library is deemed a mode
27
+ of using an interface provided by the Library.
28
+
29
+ A "Combined Work" is a work produced by combining or linking an
30
+ Application with the Library. The particular version of the Library
31
+ with which the Combined Work was made is also called the "Linked
32
+ Version".
33
+
34
+ The "Minimal Corresponding Source" for a Combined Work means the
35
+ Corresponding Source for the Combined Work, excluding any source code
36
+ for portions of the Combined Work that, considered in isolation, are
37
+ based on the Application, and not on the Linked Version.
38
+
39
+ The "Corresponding Application Code" for a Combined Work means the
40
+ object code and/or source code for the Application, including any data
41
+ and utility programs needed for reproducing the Combined Work from the
42
+ Application, but excluding the System Libraries of the Combined Work.
43
+
44
+ 1. Exception to Section 3 of the GNU GPL.
45
+
46
+ You may convey a covered work under sections 3 and 4 of this License
47
+ without being bound by section 3 of the GNU GPL.
48
+
49
+ 2. Conveying Modified Versions.
50
+
51
+ If you modify a copy of the Library, and, in your modifications, a
52
+ facility refers to a function or data to be supplied by an Application
53
+ that uses the facility (other than as an argument passed when the
54
+ facility is invoked), then you may convey a copy of the modified
55
+ version:
56
+
57
+ a) under this License, provided that you make a good faith effort to
58
+ ensure that, in the event an Application does not supply the
59
+ function or data, the facility still operates, and performs
60
+ whatever part of its purpose remains meaningful, or
61
+
62
+ b) under the GNU GPL, with none of the additional permissions of
63
+ this License applicable to that copy.
64
+
65
+ 3. Object Code Incorporating Material from Library Header Files.
66
+
67
+ The object code form of an Application may incorporate material from
68
+ a header file that is part of the Library. You may convey such object
69
+ code under terms of your choice, provided that, if the incorporated
70
+ material is not limited to numerical parameters, data structure
71
+ layouts and accessors, or small macros, inline functions and templates
72
+ (ten or fewer lines in length), you do both of the following:
73
+
74
+ a) Give prominent notice with each copy of the object code that the
75
+ Library is used in it and that the Library and its use are
76
+ covered by this License.
77
+
78
+ b) Accompany the object code with a copy of the GNU GPL and this license
79
+ document.
80
+
81
+ 4. Combined Works.
82
+
83
+ You may convey a Combined Work under terms of your choice that,
84
+ taken together, effectively do not restrict modification of the
85
+ portions of the Library contained in the Combined Work and reverse
86
+ engineering for debugging such modifications, if you also do each of
87
+ the following:
88
+
89
+ a) Give prominent notice with each copy of the Combined Work that
90
+ the Library is used in it and that the Library and its use are
91
+ covered by this License.
92
+
93
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
94
+ document.
95
+
96
+ c) For a Combined Work that displays copyright notices during
97
+ execution, include the copyright notice for the Library among
98
+ these notices, as well as a reference directing the user to the
99
+ copies of the GNU GPL and this license document.
100
+
101
+ d) Do one of the following:
102
+
103
+ 0) Convey the Minimal Corresponding Source under the terms of this
104
+ License, and the Corresponding Application Code in a form
105
+ suitable for, and under terms that permit, the user to
106
+ recombine or relink the Application with a modified version of
107
+ the Linked Version to produce a modified Combined Work, in the
108
+ manner specified by section 6 of the GNU GPL for conveying
109
+ Corresponding Source.
110
+
111
+ 1) Use a suitable shared library mechanism for linking with the
112
+ Library. A suitable mechanism is one that (a) uses at run time
113
+ a copy of the Library already present on the user's computer
114
+ system, and (b) will operate properly with a modified version
115
+ of the Library that is interface-compatible with the Linked
116
+ Version.
117
+
118
+ e) Provide Installation Information, but only if you would otherwise
119
+ be required to provide such information under section 6 of the
120
+ GNU GPL, and only to the extent that such information is
121
+ necessary to install and execute a modified version of the
122
+ Combined Work produced by recombining or relinking the
123
+ Application with a modified version of the Linked Version. (If
124
+ you use option 4d0, the Installation Information must accompany
125
+ the Minimal Corresponding Source and Corresponding Application
126
+ Code. If you use option 4d1, you must provide the Installation
127
+ Information in the manner specified by section 6 of the GNU GPL
128
+ for conveying Corresponding Source.)
129
+
130
+ 5. Combined Libraries.
131
+
132
+ You may place library facilities that are a work based on the
133
+ Library side by side in a single library together with other library
134
+ facilities that are not Applications and are not covered by this
135
+ License, and convey such a combined library under terms of your
136
+ choice, if you do both of the following:
137
+
138
+ a) Accompany the combined library with a copy of the same work based
139
+ on the Library, uncombined with any other library facilities,
140
+ conveyed under the terms of this License.
141
+
142
+ b) Give prominent notice with the combined library that part of it
143
+ is a work based on the Library, and explaining where to find the
144
+ accompanying uncombined form of the same work.
145
+
146
+ 6. Revised Versions of the GNU Lesser General Public License.
147
+
148
+ The Free Software Foundation may publish revised and/or new versions
149
+ of the GNU Lesser General Public License from time to time. Such new
150
+ versions will be similar in spirit to the present version, but may
151
+ differ in detail to address new problems or concerns.
152
+
153
+ Each version is given a distinguishing version number. If the
154
+ Library as you received it specifies that a certain numbered version
155
+ of the GNU Lesser General Public License "or any later version"
156
+ applies to it, you have the option of following the terms and
157
+ conditions either of that published version or of any later version
158
+ published by the Free Software Foundation. If the Library as you
159
+ received it does not specify a version number of the GNU Lesser
160
+ General Public License, you may choose any version of the GNU Lesser
161
+ General Public License ever published by the Free Software Foundation.
162
+
163
+ If the Library as you received it specifies that a proxy can decide
164
+ whether future versions of the GNU Lesser General Public License shall
165
+ apply, that proxy's public statement of acceptance of any version is
166
+ permanent authorization for you to choose that version for the
167
+ Library.
168
+
@@ -0,0 +1,19 @@
1
+ #!mast lib meta [A-Z]*
2
+ lib
3
+ lib/r4x
4
+ lib/r4x/e4x.rb
5
+ lib/r4x/emcascript.rb
6
+ lib/r4x/qname.rb
7
+ lib/r4x/xml_delegate.rb
8
+ lib/r4x/xmllist_delegate.rb
9
+ meta
10
+ meta/abstract
11
+ meta/authors
12
+ meta/contact
13
+ meta/package
14
+ meta/project
15
+ meta/repository
16
+ meta/version
17
+ LICENSE
18
+ README
19
+ HISTORY
data/README ADDED
@@ -0,0 +1,13 @@
1
+ = R4X
2
+
3
+ R4X is a pure-Ruby implementation of E4X.
4
+
5
+ == STATUS
6
+
7
+ This implementation follows the E4X specification to the letter.
8
+ At thei point it is only about half complete.
9
+
10
+ One difficulty with the implementation is that Ruby can not
11
+ support the exact syntax E4X designates, so an alternative
12
+ needs to be used --which has not yet been fully settled upon.
13
+
@@ -0,0 +1,330 @@
1
+
2
+ # E4X (Lite)
3
+ #
4
+ # This is a E4X library making it easy to parse and manipulate XML documents.
5
+ # It is not a compliant implementaion of E4X, but it is very close to being so
6
+ # from the end-user's point-of-view.
7
+ #
8
+ # This library uses REXML as a backend. An option to use libxml may be added in
9
+ # the future for speed.
10
+
11
+ require 'rexml/document'
12
+ require 'rexml/xpath'
13
+
14
+ #require 'facet/object/deepcopy'
15
+ require 'facet/string/shift'
16
+ require 'facet/string/pop'
17
+
18
+ require 'e4x/qname'
19
+ require 'e4x/xml_delegate'
20
+ require 'e4x/xmllist_delegate'
21
+
22
+
23
+ def xml( xmldata )
24
+ Xml.new(xmldata)
25
+ end
26
+
27
+ class Xml
28
+
29
+ # This is used it identify strings that conform to canonical XML element text.
30
+ module XmlCanonical
31
+ module_function
32
+ def ===( str )
33
+ str = str.to_s.strip
34
+ #str[0,1] == '<' && str[-1,1] == '>' # should make more robust (TODO)
35
+ md = (%r{\A \< (\w+) (.*?) \>}mix).match( str )
36
+ return false unless md #[2] =~ %r{xml:cdata=['"]\d+['"]}
37
+ ed = (%r{\< \/ #{md[1]} [ ]* \> \Z}mix).match(str)
38
+ return false unless ed
39
+ true
40
+ end
41
+ end
42
+
43
+
44
+ VALID_CLASSES = [ :element, :text, :comment, :instruction, :attribute ]
45
+
46
+ # These are for a special usage (non-standard XML); ignored for all standard purposes.
47
+ #VERB_INDICATOR = '|'
48
+ #VERB_REGEX = %r{ \< ([\w.:]+) (.*?) ([#{VERB_INDICATOR}]\d*) \> }mix
49
+
50
+ class << self
51
+ alias :__new :new
52
+ def new( xmldata, parent=nil )
53
+ case xmldata
54
+ when nil, ''
55
+ raise ArgumentError
56
+ when Xml, Symbol, XmlCanonical
57
+ __new( xmldata, parent )
58
+ when REXML::Element, REXML::Text, REXML::Attribute, REXML::Instruction
59
+ __new( xmldata, parent )
60
+ else
61
+ XmlList.new(xmldata, parent)
62
+ end
63
+ end
64
+ end
65
+
66
+ def initialize( xmldata, parent=nil )
67
+ @parent = parent
68
+ case xmldata
69
+ when Xml
70
+ @node = xmldata.__node.dup
71
+ @class = xmldata.__class.dup
72
+ @name = xmldata.__node.name.dup
73
+ when Symbol
74
+ #@node = REXML::Document.new( "<#{xmldata}></#{xmldata}>" ).root
75
+ #@node = REXML::Element.new( "<#{xmldata}></#{xmldata}>" ).root
76
+ @node = REXML::Element.new( xmldata )
77
+ @class = :element
78
+ @name = @node.name
79
+ when XmlCanonical
80
+ xmldata = xmldata.to_s
81
+ @node = REXML::Document.new( xmldata.strip ).root
82
+ #@node = REXML::Element.new( xmldata.strip )
83
+ @class = :element
84
+ @name = @node.name
85
+ when REXML::Element
86
+ @node = xmldata
87
+ @class = :element
88
+ @name = @node.name
89
+ when REXML::Text
90
+ @node = xmldata
91
+ @class = :text
92
+ @name = nil
93
+ when REXML::Attribute
94
+ @node = xmldata
95
+ @class = :attribute
96
+ @name = xmldata.name
97
+ when REXML::Instruction
98
+ @node = xmldata
99
+ @class = :instruction
100
+ @name = xmldata.target
101
+ else
102
+ raise ArgumentError, "invlaid xml"
103
+ end
104
+ @self ||= XmlDelegate.new(self)
105
+ end
106
+
107
+ # These are reserved tag names, i.e. they can't be used as xml tags
108
+ # and then accessed via the call syntax of E4X.
109
+ #
110
+ # self
111
+ # __node
112
+ # __class
113
+ # to_s
114
+ # to_i
115
+ # each
116
+ #
117
+
118
+ # This is how to access the underlying Xml object, i.e. via the delegate.
119
+ def self ; @self ; end
120
+
121
+ # This is how the delegate accesses the node.
122
+ def __node ; @node ; end
123
+
124
+ # This is how the delegate accesses the node classification.
125
+ def __class ; @class ; end
126
+
127
+ # Important for this to work in string interpolation.
128
+ def to_s() @node.to_s ; end
129
+
130
+ # ?
131
+ def to_i() @node.to_s.to_i; end
132
+
133
+ # (neccessary?) FIX!!!
134
+ def each()
135
+ @node.each_child { |c| yield(c) }
136
+ end
137
+
138
+ # Shortcut for add.
139
+ def <<( n )
140
+ @self.add( n )
141
+ end
142
+
143
+ # XPath for all elements.
144
+ def * ; @self.get('*') ; end
145
+
146
+ # Shortcut for XPath '@*', meaning all attributes.
147
+ def _ ; @self.get('@*') ; end
148
+
149
+ # XPath get operator.
150
+ def []( key )
151
+ @self.get( key )
152
+ end
153
+
154
+ #XPath put operator.
155
+ def []=( key, val )
156
+ @self.put( key, val )
157
+ end
158
+
159
+ # Here's where all the fun's at!
160
+ # It's more complicated then it looks ;-)
161
+ def method_missing( sym, *args )
162
+ sym = sym.to_s
163
+ if sym.slice(-1) == '='
164
+ self["#{sym.pop}"] = args[0]
165
+ else
166
+ self["#{sym}"]
167
+ end
168
+ end
169
+
170
+ end
171
+
172
+ #
173
+ # XmlList
174
+ #
175
+ class XmlList
176
+
177
+ class << self
178
+ alias_method( :__new, :new )
179
+ def new( xd=[], to=nil, tp=nil )
180
+ case xd
181
+ when XmlList
182
+ xd
183
+ else
184
+ __new( xd, to, tp )
185
+ end
186
+ end
187
+ end
188
+
189
+ def initialize( xd=[], to=nil, tp=nil )
190
+ @self = XmlListDelegate.new(self)
191
+ case xd
192
+ when []
193
+ @list = []
194
+ @target_object = to
195
+ @target_property = tp
196
+ when Xml
197
+ @list = [xd]
198
+ @target_object = xd.self.parent
199
+ @target_property = xd.self.name
200
+ else
201
+ xd = REXML::Document.new(%{<_>#{xd}</_>}).root
202
+ a = []; xd.each{ |n| a << Xml.new(n) }
203
+ @list = a
204
+ @target_object = nil
205
+ @target_property = nil
206
+ end
207
+ end
208
+
209
+ # This is how to access the underlying Xml object, i.e. via the delegate.
210
+ def self ; @self ; end
211
+
212
+ # This is how the delegate accesses the node.
213
+ def __list ; @list ; end
214
+
215
+ # This is how the delegate accesses the node classification.
216
+ def __class ; :xmllist ; end
217
+
218
+ # This is how the delegate accesses the node classification.
219
+ def __target_object ; @target_object ; end
220
+ def __target_object=(to) ; @target_object = to ; end
221
+
222
+ # This is how the delegate accesses the node classification.
223
+ def __target_property ; @target_property ; end
224
+ def __target_property=(tp) ; @target_property = tp ; end
225
+
226
+ # Important for this to work in string interpolation.
227
+ def to_s() @list.to_s ; end
228
+
229
+ # ?
230
+ def to_i() @list.to_s.to_i; end
231
+
232
+ # each
233
+ def each(&blk) ; @list.each(&blk) ; end
234
+
235
+ # Shortcut for add.
236
+ def <<( n )
237
+ @self.add( n )
238
+ end
239
+
240
+ # XPath for all elements.
241
+ def * ; @self.get('*') ; end
242
+
243
+ # Shortcut for XPath '@*', meaning all attributes.
244
+ def _ ; @self.get('@*') ; end
245
+
246
+ def []( v )
247
+ @self.get( v )
248
+ end
249
+
250
+ def []=( prop, v )
251
+ @self.put( prop , v )
252
+ end
253
+
254
+ #
255
+ def method_missing( sym, *args )
256
+ sym = sym.to_s
257
+ p sym
258
+ if (args.size > 0)
259
+ self[0].send( sym, args )
260
+ else
261
+ self[0].send( sym )
262
+ end
263
+ end
264
+
265
+ end
266
+
267
+
268
+
269
+ # test
270
+ if $0 == __FILE__
271
+
272
+ XmlList.new('abc <tab>123</tab>')
273
+
274
+ x = xml %Q{
275
+ <people id="666-99-0989" lick="me">
276
+ <person username="trans">
277
+ <name>
278
+ Tom
279
+ ...
280
+ 123
281
+ </name>
282
+ <age>35</age>
283
+ </person>
284
+ <person username="jenasmom">
285
+ <name>Becky</name>
286
+ <age>32</age>
287
+ </person>
288
+ </people>
289
+ }
290
+
291
+ puts x.*
292
+ puts x._
293
+
294
+ puts x.self.name
295
+ puts x.self.attributes
296
+
297
+ puts x.person
298
+ puts x['person']
299
+ puts x._id
300
+ puts x['@id']
301
+ p x
302
+ puts x[1] # skip whatespace?
303
+ puts "HERE"
304
+ x << xml(%{<fred id="10">Timmy</fred>})
305
+
306
+ puts x['@*']
307
+
308
+ end
309
+
310
+
311
+
312
+ # SCRAP
313
+
314
+ # def __verb?(str)
315
+ # str = str.strip
316
+ # return nil unless __tag?(str)
317
+ # md = (%r{\A \< (\w+) (.*?) \>}mix).match( str )
318
+ # p md
319
+ # return nil unless md[2] =~ %r{xml:cdata=['"]\d+['"]}
320
+ # ed = (%r{\< \/ #{n} [ ]* \> \Z}mix).match(str)
321
+ # return nil unless ed
322
+ # c = md[0] + '<![CDATA[' + str[md.end(0)...ed.begin] + ']]>' + ed[0]
323
+ # p c
324
+ # c
325
+ # #str = str.sub( %r{\A \< (\w+) .*? \>}mix ) { |m| n=$1 ; "#{m}<![CDATA[" }
326
+ # #str = str.sub( %r{\< \/ #{n} [ ]* \> \Z}mix ) { |m| "]]>#{m}" }
327
+ # # n << md.post_match.gsub(%r{\< \/ #{md[1]} [ ]* \> \Z}mix, '') #[0...(md.post_match.rindex('<'))] # not robust enough
328
+ # # n << "]]>"
329
+ # # n << "</#{md[1]}>"
330
+ # end
@@ -0,0 +1,4 @@
1
+
2
+ module EMCAScript
3
+
4
+ end
@@ -0,0 +1,87 @@
1
+
2
+ # Defines QName and AttributeName classes.
3
+
4
+ class QName
5
+
6
+ class << self
7
+
8
+ alias :__new :new
9
+
10
+ def new( name_or_namespace, name=nil )
11
+ case name_or_namespace
12
+ when QName
13
+ return name_or_namespace
14
+ when nil
15
+ if QName === name or name.class == "QName"
16
+ return name.dup
17
+ else
18
+ __new(name_or_namespace, name)
19
+ end
20
+ else
21
+ __new(name_or_namespace, name )
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ attr :name
28
+ attr :local_name
29
+ attr :uri
30
+ attr :prefix
31
+
32
+ def initialize( namespace, name )
33
+ @name = name.local_name.to_s # to_String
34
+ case namespace
35
+ when nil, ''
36
+ namespace = (name == '*' ? nil : get_default_namespace )
37
+ end
38
+ @local_name = name
39
+ unless namespace
40
+ @uri = nil
41
+ @prefix = nil
42
+ else
43
+ namespace = Namespace.new( namespace )
44
+ @uri = namespace.uri
45
+ @prefix = namespace.prefix
46
+ end
47
+ end
48
+
49
+ #
50
+ def to_s
51
+ s = ''
52
+ if uri != ''
53
+ unless uri
54
+ s = '*::'
55
+ else
56
+ s = "#{uri}::"
57
+ end
58
+ end
59
+ "#{s}#{local_name}"
60
+ end
61
+
62
+ #
63
+ def get_namespace( in_scope_namespaces=nil )
64
+ raise 'no uri [should not have occured]' unless uri
65
+ in_scope_namespaces ||= []
66
+ ns = in_scope_namespaces.find { |n| uri == n.uri } # prefix == n.prefix ?
67
+ ns = Namespace.new( uri ) unless ns # or ns = Namespace.new( prefix, uri ) ?
68
+ ns
69
+ end
70
+
71
+ end
72
+
73
+
74
+ class AttributeName
75
+
76
+ attr :name
77
+
78
+ def initialize( s )
79
+ @name = QName.new(s)
80
+ end
81
+
82
+ def to_s
83
+ "@#{@name}"
84
+ end
85
+
86
+ end
87
+
@@ -0,0 +1,297 @@
1
+
2
+ class Xml #< BlankSlate
3
+
4
+ class XmlDelegate
5
+
6
+ include Enumerable
7
+
8
+ def initialize( x )
9
+ @x = x
10
+ end
11
+
12
+ def node ; @x.__node ; end
13
+ def name ; @x.__node.name ; end
14
+ def text ; @x.__node.text ; end
15
+
16
+ def klass ; @x.__class ; end
17
+ def parent ; @x.__parent ; end
18
+ def attributes ; @x.__node.attributes ; end
19
+ def value ; @x.__node.children.join('') ; end
20
+
21
+ #
22
+ def get(prop)
23
+ if Integer === prop
24
+ l = to_XmlList
25
+ return l.__get__(prop)
26
+ end
27
+ n = prop.self.to_XmlName
28
+ l = XmlList.new([],@x,n)
29
+ if AttributeName === n
30
+ @x.attributes.each { |a|
31
+ if ( ( n.name.local_name =='*' || n.name.local_name == a.name.local_name ) and
32
+ ( n.name.uri == nil || n.name.uri == a.name.uri ) )
33
+ l.append(a)
34
+ end
35
+ }
36
+ return l
37
+ end
38
+ (0...length).each { |k|
39
+ if ( (n.local_name == '*') or
40
+ ((Element === @x[k]) and (@x[k].name.local_name == a.name.local_name)) ) and
41
+ ( (n.uri == nil) or ((@x[k].__class__ == "element") and (n.uri == @x[k].name.uri)) )
42
+ l.append(@x[k])
43
+ end
44
+ }
45
+ return l
46
+ end
47
+
48
+ # def get( prop )
49
+ # if prop.kind_of?(Integer)
50
+ # l = to_XmlList
51
+ # return l.self.get( prop )
52
+ # end
53
+ # #n = prop.to_XmlName
54
+ # l = XmlList.new([], @x, prop)
55
+ # # if prop =~ /^[@_]/
56
+ # # @x.__node.attributes.each{ |a|
57
+ # # l.self.append a
58
+ # # }
59
+ # # return l
60
+ # # end
61
+ # REXML::XPath.each( @x.__node, prop.to_s ) { |elem|
62
+ # l.self.append( Xml.new( elem ) )
63
+ # }
64
+ # return l
65
+ # end
66
+
67
+ # def put( key, val )
68
+ # if key =~ /^[@_]/
69
+ # @x.__node.attributes[ key.shift ] = value
70
+ # elsif gk = get(key)
71
+ # case gk.size
72
+ # when 0
73
+ # add "<#{key}>#{val}</#{key}>"
74
+ # when 1
75
+ # gk[0] #?
76
+ # else
77
+ # raise "unimplemented"
78
+ # #? What to do then?
79
+ # end
80
+ # else
81
+ # insert( key, val )
82
+ # end
83
+ # end
84
+
85
+ #
86
+ def put( prop, val )
87
+ if !(Xml === val or XmlList === val) or ( [:text,:attribute].include?(val.self.class) )
88
+ c = val.to_s
89
+ else
90
+ c = val.self.deepcopy
91
+ end
92
+ raise ArgumentError if Numeric === prop
93
+ return if [:text,:attribute,:comment,:instruction].include?( klass )
94
+ n = prop.to_XmlName
95
+ default_namespace = get_default_namespace()
96
+ if AttributeName === n
97
+ return unless is_XmlName(n.self.name)
98
+ if XmlList === c
99
+ if c.length === 0
100
+ c = ''
101
+ else
102
+ #s = c[0].to_s
103
+ #(1...c.length).each { |i| s += " #{c[i].to_s}"
104
+ s = c.join(' ')
105
+ end
106
+ else
107
+ c = c.to_s
108
+ end
109
+ a = nil
110
+ x.attributes.each { |j|
111
+ if (n.name.local_name == j.name.local_name) and (n.name.uri == nil or n.name.uri == j.name.uri)
112
+ a = j unless a
113
+ else
114
+ x.delete(j.name)
115
+ end
116
+ }
117
+ unless a
118
+ unless n.name.uri
119
+ nons = Namespace.new
120
+ name = QName.new( nons, n.name )
121
+ else
122
+ name = QName.new( n.name )
123
+ end
124
+ a = Xml.new { |s| s.name=name ; s.classification=:attribute ; s.parent=x }
125
+ x.attributes << a
126
+ ns = name.get_namespace
127
+ x.add_in_scope_namespace(ns)
128
+ end
129
+ a.value = c
130
+ return
131
+ end
132
+ is_valid_name = is_XmlName(n)
133
+ return if !is_valid_name and n.local_name != '*'
134
+ i = nil
135
+ primitive_assign = ((!(Xml === c or XmlList === c)) and n.local_name != '*')
136
+ (x.length-1).downto(0) { |k|
137
+ if ( (n.local_name == '*') or ( (@x[k].classification == :element) and (@x[k].name.locall_name == n.local_name) ) ) and
138
+ ( (n.uri == nil) or ( (@x[k].classification==:element) and (n.uri == @x[k].name.uri) ) )
139
+ if i
140
+ x.delete_by_index(i.to_s)
141
+ i = k
142
+ end
143
+ end
144
+ }
145
+ unless i
146
+ i = x.length
147
+ if primitive_assign
148
+ unless n.uri
149
+ name = QName.new( default_namespace, n )
150
+ else
151
+ name = QName.new(n)
152
+ end
153
+ y=Xml.new{|s| s.name=name; s.classification=:element; s.parent=x}
154
+ ns=name.get_namespace
155
+ x.replace(i.to_s,y)
156
+ y.add_in_scope_namespace(ns)
157
+ end
158
+ end
159
+ if primitive_asign
160
+ # x[i].delete_all_properties
161
+ s = c.to_s
162
+ x[i].replace("0",s) if s != ''
163
+ else
164
+ x.replace(i.to_s,c)
165
+ end
166
+ return
167
+ end
168
+
169
+ def add( nodes )
170
+ case nodes
171
+ when XmlList
172
+ nodes.each { |n| @x.__node << n.__node }
173
+ else
174
+ @x.__node << nodes.__node
175
+ end
176
+ @x
177
+ end
178
+
179
+ #
180
+ def delete(prop)
181
+ raise ArgumentError if Numeric === prop
182
+ n = prop.self.to_XmlName
183
+ if AttributeName === n
184
+ attribs = attributes.collect{|a|
185
+ if ((n.name.local_name == '*') or (n.name.local_name == a.name.local_name)) and
186
+ ((n.name.uri == nil) or (n.name.uri == a.name.uri))
187
+ a.parent = nil
188
+ nil
189
+ else
190
+ a
191
+ end
192
+ }.compact
193
+ return true
194
+ end
195
+ dp = 0
196
+ (0...length).each { |q|
197
+ if ((n.local_name == '*') or
198
+ (@x[q].self.class == :element and @x[q].self.name.local_namespace == n.local_name)) and
199
+ ((n.uri == nil) or (@x[q].self.class == :element and n.uri == @x[q].self.name.uri))
200
+ x[q].parent = nil
201
+ x.delete_at(q)
202
+ dp+=1
203
+ else
204
+ if dp > 0
205
+ @x[q - dp] = x[q]
206
+ @x.delete_at(q)
207
+ end
208
+ end
209
+ }
210
+ return true
211
+ end
212
+
213
+ #
214
+ def delete_by_index(prop)
215
+ end
216
+
217
+ #
218
+ def default_value
219
+ end
220
+
221
+ #
222
+ def has_property
223
+ end
224
+
225
+ #
226
+ def deep_copy
227
+ end
228
+
229
+ #
230
+ def descendents(prop)
231
+ end
232
+
233
+ #
234
+ def equals(value)
235
+ end
236
+
237
+ #
238
+ def resolve_value
239
+ @x
240
+ end
241
+
242
+ #
243
+ def insert(prop,value)
244
+ end
245
+
246
+ #
247
+ def replace(prop,value)
248
+ end
249
+
250
+ #
251
+ def add_in_scope_namespace__(namespace)
252
+ end
253
+
254
+ def delete( key )
255
+ @x.__node.delete_element( key ) #string key is an xpath
256
+ end
257
+
258
+
259
+ # Conversions
260
+
261
+ def to_XmlList
262
+ XmlList.new( @x )
263
+ end
264
+
265
+ # def to_XmlList
266
+ # target_object = self.__parent__
267
+ # target_poperty = self.__name__
268
+ # l = XmlList.new([self], target_object, target_property)
269
+ # end
270
+
271
+ def to_XmlName
272
+ s = to_String
273
+ if s =~ /^[_@]/
274
+ to_AttributeName( s.shift )
275
+ else
276
+ QName.new(s)
277
+ end
278
+ end
279
+
280
+ def to_String
281
+ return value if [:attribute, :text].include?(@x)
282
+ if has_simple_content
283
+ s = ''
284
+ @x.each { |e| s << e unless [:comment,:instruction].include?(e.self.class) }
285
+ return s
286
+ else
287
+ to_XmlString
288
+ end
289
+ end
290
+
291
+ def to_XmlString( ancestor_namespaces=nil, indent_level=nil )
292
+
293
+ end
294
+
295
+ end
296
+
297
+ end
@@ -0,0 +1,165 @@
1
+
2
+ class XmlList
3
+
4
+ class XmlListDelegate
5
+
6
+ def initialize( x )
7
+ @x = x
8
+ end
9
+
10
+ def list ; @x.__list ; end
11
+ def class ; @x.__class ; end
12
+
13
+ def target_object ; @x.__target_object ; end
14
+ def target_property ; @x.__target_property ; end
15
+ def target_object=(to) ; @x.__target_object = to ; end
16
+ def target_property=(tp) ; @x.__target_property = tp ; end
17
+
18
+ def get( prop )
19
+ if prop.kind_of?(Integer)
20
+ return @x.__list.at( prop )
21
+ end
22
+ l = XmlList.new( [], @x, prop )
23
+ 0...length { |i|
24
+ gq = @x[i].self.get( prop )
25
+ l.self.append( gq ) if gq.self.length > 0
26
+ }
27
+ return l
28
+ end
29
+
30
+ def put( prop, v )
31
+ if prop.kind_of?(Integer)
32
+ i = prop
33
+ if @x.__target_object
34
+ r = @x.__target_object.self.resolve_value
35
+ return unless r
36
+ else
37
+ r = nil
38
+ end
39
+ if i >= @x.__list.length
40
+ if r.is_a?(XmlList)
41
+ return if r.self.length != 1
42
+ else
43
+ r = r[0]
44
+ end
45
+ y = Xml.new( @x.__target_property.to_sym, r )
46
+ if @x.__target_property =~ /^[@_]/
47
+ attribute_exists = r.self.get( y.self.name )
48
+ return if attributes_exists.self.length > 0
49
+ y.self.class = :attribute
50
+ elsif (!@x.__target_property) or @x.__target_property.local_name== '*'
51
+ y.self.name = nil
52
+ y.self.class = :text
53
+ else
54
+ t.self.class = :element
55
+ end
56
+ i = length
57
+ if y.self.class != :attribute
58
+ if y.self.parent
59
+ if i > 0
60
+ j = 0
61
+ while ((j < (y.self.parent.self.length - 1)) and (y.self.parent[j] != @x[i-1])) do
62
+ j += 1
63
+ end
64
+ else
65
+ j = y.self.parent.self.length - 1
66
+ end
67
+ end
68
+ if v.is_a?(Xml)
69
+ y.self.name = v.slef.name
70
+ elsif v.is_a?(XmlList)
71
+ y.self.name = v.self.property_name
72
+ else
73
+ raise "invalid type"
74
+ end
75
+ end
76
+ @x.self.append y
77
+ end
78
+ if ( !( v.is_a?(Xml) or v.is_a?(XmlList) ) or [:text, :attribute].include?(v.self.class) )
79
+ v = v.to_s #to_String
80
+ end
81
+ if @x[i].self.class == :attribute
82
+ @x[i].self.parent.self.put( x[i].self.name, v )
83
+ attr = x[i].self.parent.self.get( x[i].self.name )
84
+ x[i] = attr[0]
85
+ elsif v.is_a?(XmlList)
86
+ c = v.dup
87
+ parent = x[i].self.parent
88
+ if parent
89
+ q = parent.self.index(@x[i])
90
+ parent.self.replace( q, c )
91
+ (0...c.self.length).each { |j| c[j] = parent[q+j] }
92
+ end
93
+ (c.self.length-1..i).each { |j| @x[j+c.self.length] = @x[j] }
94
+ (0...c.self.length).each { |j| @x[i+j] = c[j] }
95
+ elsif v.is_a?(Xml) or [:text, :comment, :instruction].include?(@x[i].self.class)
96
+ parent = @x[i].self.parent
97
+ if parent
98
+ q = parent.self.index(@x[i])
99
+ parent.self.replace( q, v )
100
+ v = parent[q]
101
+ end
102
+ x[i] = v
103
+ else
104
+ x[i].self.put( '*', v )
105
+ end
106
+ else
107
+ if length == 0
108
+ r = @x.resolve_value
109
+ return if !r or r.self.length != 1
110
+ @x.self.append( r )
111
+ end
112
+ @x[0].self.put( prop, v )
113
+ end
114
+ return
115
+ end
116
+
117
+ def append( v )
118
+ i = @x.self.length
119
+ n = 1
120
+ case v
121
+ when XmlList
122
+ @x.__target_object = v.self.target_object
123
+ @x.__target_property = v.self.target_property
124
+ n = v.self.length
125
+ return if n == 0
126
+ (0...v.self.length).each { |i| @x[i+j] = v[j] }
127
+ when Xml
128
+ @x.__target_object = v.self.parent
129
+ if v.self.class == :instruction
130
+ @x.__target_property = nil
131
+ else
132
+ @x.__target_property = v.self.name
133
+ end
134
+ @x[i] = v
135
+ # @x.length += n
136
+ else
137
+ raise 'Xml or XmlList expected'
138
+ end
139
+ end
140
+
141
+ def resolve_value
142
+ return if length > 0
143
+ unless target_object and target_property
144
+ if target_property =~ /^[_@]/ or target_property.local_name == '*'
145
+ return nil
146
+ end
147
+ end
148
+ base = target_object.self.resolve_value # recursive
149
+ return nil unless base
150
+ target = base.self.get( target_property )
151
+ if target.self.length == 0
152
+ return nil if base.is_a?(XmlList) and base.self.length > 1
153
+ base.self.put( target_property, '' )
154
+ target = base.self.get( target_property )
155
+ end
156
+ return target
157
+ end
158
+
159
+ def length
160
+ @x.__list.length
161
+ end
162
+
163
+ end
164
+
165
+ end
@@ -0,0 +1 @@
1
+ R4X is an implementation of E4X for Ruby.
@@ -0,0 +1 @@
1
+ Thomas Sawyer
@@ -0,0 +1 @@
1
+ rubyworks-mailinglist@rubyforge.org
@@ -0,0 +1 @@
1
+ r4x
@@ -0,0 +1 @@
1
+ rubyworks
@@ -0,0 +1 @@
1
+ git://github.com/rubyworks/r4x.git
@@ -0,0 +1 @@
1
+ 0.5.0
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: r4x
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - rubyworks-mailinglist@rubyforge.org
8
+ - Thomas Sawyer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-09-27 00:00:00 -04:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: R4X is an implementation of E4X for Ruby.
18
+ email: rubyworks-mailinglist@rubyforge.org
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README
25
+ - MANIFEST
26
+ - LICENSE
27
+ - HISTORY
28
+ files:
29
+ - lib/r4x/e4x.rb
30
+ - lib/r4x/emcascript.rb
31
+ - lib/r4x/qname.rb
32
+ - lib/r4x/xml_delegate.rb
33
+ - lib/r4x/xmllist_delegate.rb
34
+ - meta/abstract
35
+ - meta/authors
36
+ - meta/contact
37
+ - meta/package
38
+ - meta/project
39
+ - meta/repository
40
+ - meta/version
41
+ - LICENSE
42
+ - README
43
+ - HISTORY
44
+ - MANIFEST
45
+ has_rdoc: true
46
+ homepage:
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --inline-source
52
+ - --title
53
+ - r4x api
54
+ - --main
55
+ - README
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project: r4x
73
+ rubygems_version: 1.3.5
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: R4X is an implementation of E4X for Ruby.
77
+ test_files: []
78
+