r4x 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+