r4x 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +0 -0
- data/LICENSE +168 -0
- data/MANIFEST +19 -0
- data/README +13 -0
- data/lib/r4x/e4x.rb +330 -0
- data/lib/r4x/emcascript.rb +4 -0
- data/lib/r4x/qname.rb +87 -0
- data/lib/r4x/xml_delegate.rb +297 -0
- data/lib/r4x/xmllist_delegate.rb +165 -0
- data/meta/abstract +1 -0
- data/meta/authors +1 -0
- data/meta/contact +1 -0
- data/meta/package +1 -0
- data/meta/project +1 -0
- data/meta/repository +1 -0
- data/meta/version +1 -0
- metadata +78 -0
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
|
+
|
data/MANIFEST
ADDED
@@ -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
|
+
|
data/lib/r4x/e4x.rb
ADDED
@@ -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
|
data/lib/r4x/qname.rb
ADDED
@@ -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
|
data/meta/abstract
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
R4X is an implementation of E4X for Ruby.
|
data/meta/authors
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Thomas Sawyer
|
data/meta/contact
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rubyworks-mailinglist@rubyforge.org
|
data/meta/package
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
r4x
|
data/meta/project
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rubyworks
|
data/meta/repository
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
git://github.com/rubyworks/r4x.git
|
data/meta/version
ADDED
@@ -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
|
+
|