hutch-xamplr 1.0.5 → 1.1.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/Rakefile +1 -0
- data/VERSION.yml +2 -2
- data/examples/random-people-shared-addresses/Makefile +2 -2
- data/examples/random-people-shared-addresses/batch-load-users.rb +2 -5
- data/examples/random-people-shared-addresses/find-mentions.rb +1 -4
- data/examples/random-people-shared-addresses/find-people-by-address.rb +1 -4
- data/examples/random-people-shared-addresses/optimise.rb +1 -4
- data/examples/random-people-shared-addresses/people.rb +0 -15
- data/examples/random-people-shared-addresses/query.rb +1 -4
- data/examples/random-people-shared-addresses/query2.rb +1 -4
- data/examples/random-people-shared-addresses/results.write.BASELINE +298 -0
- data/examples/random-people-shared-addresses/results.write.NEW_ATTR_ENCODING +294 -0
- data/examples/random-people-shared-addresses/settings.rb +3 -0
- data/examples/random-people/batch-load-users.rb +1 -4
- data/examples/random-people/optimise.rb +1 -4
- data/examples/random-people/people.rb +0 -3
- data/examples/random-people/query.rb +1 -5
- data/examples/random-people/query2.rb +1 -4
- data/examples/random-people/settings.rb +3 -0
- data/examples/random-people/what-to-query-on.rb +1 -3
- data/examples/read-testing/Makefile +10 -0
- data/examples/read-testing/load.rb +65 -0
- data/examples/read-testing/read.rb +51 -0
- data/examples/read-testing/results.read.BASELINE +6 -0
- data/examples/read-testing/results.read.FAST +5 -0
- data/examples/read-testing/rrr.rb +87 -0
- data/examples/read-testing/settings.rb +2 -0
- data/examples/read-testing/xampl-gen.rb +36 -0
- data/examples/read-testing/xml/text.xml +8 -0
- data/lib/xamplr.rb +10 -1
- data/lib/xamplr/exceptions.rb +97 -0
- data/lib/xamplr/from-xml-orig.rb +350 -0
- data/lib/xamplr/from-xml.rb +272 -183
- data/lib/xamplr/handwritten/example.rb +0 -58
- data/lib/xamplr/handwritten/hand-example.rb +0 -27
- data/lib/xamplr/handwritten/test-handwritten.rb +0 -37
- data/lib/xamplr/mixins.rb +10 -48
- data/lib/xamplr/persist-to-xml.rb +249 -0
- data/lib/xamplr/persistence.rb +44 -412
- data/lib/xamplr/persistence.rb.more_thread_safe +0 -13
- data/lib/xamplr/persistence.rb.partially_thread_safe +0 -13
- data/lib/xamplr/persister.rb +298 -0
- data/lib/xamplr/{persister → persisters}/caches.rb +0 -0
- data/lib/xamplr/{persister → persisters}/caching.rb +1 -1
- data/lib/xamplr/{persister → persisters}/filesystem.rb +4 -5
- data/lib/xamplr/{persister → persisters}/in-memory.rb +1 -1
- data/lib/xamplr/{persister → persisters}/simple.rb +0 -0
- data/lib/xamplr/{persister → persisters}/tokyo-cabinet.rb +53 -15
- data/lib/xamplr/simpleTemplate/{input-c.r4 → obsolete/input-c.r4} +0 -0
- data/lib/xamplr/simpleTemplate/{play.r6.txt → obsolete/play.r6.txt} +0 -0
- data/lib/xamplr/simpleTemplate/{play_more.r6.txt → obsolete/play_more.r6.txt} +0 -0
- data/lib/xamplr/simpleTemplate/{test001.r5 → obsolete/test001.r5} +0 -0
- data/lib/xamplr/simpleTemplate/{test002.r5 → obsolete/test002.r5} +0 -0
- data/lib/xamplr/simpleTemplate/{test003.r5 → obsolete/test003.r5} +0 -0
- data/lib/xamplr/templates/child_indexed.template +1 -1
- data/lib/xamplr/templates/element_classes.template +1 -1
- data/lib/xamplr/templates/element_data.template +0 -39
- data/lib/xamplr/templates/element_empty.template +0 -40
- data/lib/xamplr/templates/element_mixed.template +0 -41
- data/lib/xamplr/templates/element_simple.template +0 -40
- data/lib/xamplr/test-support/bench.rb +6 -26
- data/lib/xamplr/test-support/test.rb +1 -89
- data/lib/xamplr/visitor.rb +0 -778
- data/lib/xamplr/visitors.rb +573 -0
- data/lib/xamplr/xampl-generator.rb +1 -1
- data/lib/xamplr/xampl-hand-generated.rb +0 -85
- data/lib/xamplr/xampl-module.rb +36 -0
- data/lib/xamplr/xampl-object-internals.rb +6 -0
- data/lib/xamplr/xampl-object.rb +10 -341
- data/lib/xamplr/xampl-persisted-object.rb +122 -0
- data/lib/xamplr/xml-text.rb +117 -0
- metadata +53 -18
- data/lib/xamplr/persister/subversion.rb +0 -61
- data/lib/xamplr/rac.sh +0 -6
- data/lib/xamplr/rac_gen.sh +0 -1
- data/lib/xamplr/templates/child_indexed.template.000 +0 -87
@@ -0,0 +1,350 @@
|
|
1
|
+
require "xamplr-pp"
|
2
|
+
|
3
|
+
module Xampl
|
4
|
+
|
5
|
+
class FromXML_original < Xampl_PP
|
6
|
+
|
7
|
+
attr :checkWellFormed, false
|
8
|
+
attr :is_realising, false
|
9
|
+
attr :tokenise_content, false
|
10
|
+
|
11
|
+
@@by_tag = {}
|
12
|
+
@@by_ns_tag = {}
|
13
|
+
|
14
|
+
def initialize(recovering=false)
|
15
|
+
super()
|
16
|
+
@recovering = recovering
|
17
|
+
end
|
18
|
+
|
19
|
+
def FromXML_original.reset_registry
|
20
|
+
@@by_tag = {}
|
21
|
+
@@by_ns_tag = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def FromXML_original.register(tag, ns_tag, klass)
|
25
|
+
@@by_ns_tag[ns_tag] = [ klass ]
|
26
|
+
a = @@by_tag[tag]
|
27
|
+
if (nil == a) then
|
28
|
+
@@by_tag[tag] = [ klass ]
|
29
|
+
else
|
30
|
+
found = false
|
31
|
+
a.each { | thing | found = found | (thing == klass) }
|
32
|
+
a << klass unless found
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def FromXML_original.registered(name)
|
37
|
+
klass = @@by_ns_tag[name]
|
38
|
+
klass = @@by_tag[name] unless klass
|
39
|
+
klass = [] unless klass
|
40
|
+
return klass
|
41
|
+
end
|
42
|
+
|
43
|
+
def resolve(name)
|
44
|
+
return name
|
45
|
+
end
|
46
|
+
|
47
|
+
def setup_parse(filename, tokenise_content=true, is_realising=false)
|
48
|
+
@processNamespace = true
|
49
|
+
@reportNamespaceAttributes = false
|
50
|
+
@checkWellFormed = false
|
51
|
+
@resolver = self
|
52
|
+
|
53
|
+
@is_realising = is_realising
|
54
|
+
@tokenise_content = tokenise_content
|
55
|
+
|
56
|
+
setInput(File.new(filename))
|
57
|
+
end
|
58
|
+
|
59
|
+
def setup_parse_string(string, tokenise_content=true, is_realising=false)
|
60
|
+
@processNamespace = true
|
61
|
+
@reportNamespaceAttributes = false
|
62
|
+
@checkWellFormed = false
|
63
|
+
@resolver = self
|
64
|
+
|
65
|
+
@is_realising = is_realising
|
66
|
+
@tokenise_content = tokenise_content
|
67
|
+
|
68
|
+
setInput(string)
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse(filename, tokenise_content=true, is_realising=false)
|
72
|
+
begin
|
73
|
+
setup_parse(filename, tokenise_content, is_realising)
|
74
|
+
element, ignore = parse_element
|
75
|
+
return element
|
76
|
+
rescue Exception => e
|
77
|
+
puts "trouble parsing file: '#{filename}'"
|
78
|
+
puts "Exception: #{e}"
|
79
|
+
raise
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def realise_string(string, tokenise_content=true, target=nil)
|
84
|
+
return parse_string(string, tokenise_content, true, target)
|
85
|
+
end
|
86
|
+
|
87
|
+
def parse_string(string, tokenise_content=true, is_realising=false, target=nil)
|
88
|
+
begin
|
89
|
+
setup_parse_string(string, tokenise_content, is_realising)
|
90
|
+
element, ignore = parse_element(nil, target)
|
91
|
+
return element
|
92
|
+
rescue Exception => e
|
93
|
+
puts "trouble parsing string: '#{string}'"
|
94
|
+
puts "Exception: #{e}"
|
95
|
+
raise
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def FromXML_original.tokenise_string(str, strip=true)
|
100
|
+
return nil unless str
|
101
|
+
str.strip! if strip
|
102
|
+
str.gsub!(/[ \n\r\t][ \n\r\t]*/, " ")
|
103
|
+
return str
|
104
|
+
end
|
105
|
+
|
106
|
+
def parse_element(parent=nil, target=nil)
|
107
|
+
next_interesting_event unless parent
|
108
|
+
|
109
|
+
existing_element = nil
|
110
|
+
element = nil
|
111
|
+
|
112
|
+
requires_caching = false
|
113
|
+
|
114
|
+
if startElement? then
|
115
|
+
if ((nil != @namespace) and (0 < @namespace.size)) then
|
116
|
+
klass_name = "{#{@namespace}}#{@name}"
|
117
|
+
klasses = FromXML_original.registered(klass_name)
|
118
|
+
if (0 == klasses.size) then
|
119
|
+
xml_text = XMLText.new
|
120
|
+
xml_text.build(self)
|
121
|
+
xml_text = parent.note_adding_text_content(xml_text, @is_realising)
|
122
|
+
parent.add_content(xml_text, @tokenise_content) if xml_text
|
123
|
+
# puts "#{__LINE__ }:: add_content [#{xml_text}] --> [#{parent.content}]"
|
124
|
+
return xml_text, false
|
125
|
+
end
|
126
|
+
if (1 < klasses.size) then
|
127
|
+
raise XamplException.new("there is more than one '#{@name}' tag in namespace '#{@namespace}'\nplease report this error")
|
128
|
+
end
|
129
|
+
else
|
130
|
+
klasses = FromXML_original.registered(@name)
|
131
|
+
if (0 == klasses.size) then
|
132
|
+
raise XamplException.new("do not recognise tag '#{@name}' (no namespace specified)")
|
133
|
+
end
|
134
|
+
if (1 < klasses.size) then
|
135
|
+
raise XamplException.new("there is more than one '#{@name}' tag (no namespace specified)")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
unless @is_realising then
|
140
|
+
@attributeValue.size.times do |i|
|
141
|
+
FromXML_original.tokenise_string @attributeValue[i]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
if target then
|
146
|
+
element = target
|
147
|
+
target.load_needed = false
|
148
|
+
target = nil
|
149
|
+
element.init_attributes(@attributeName, @attributeNamespace, @attributeValue)
|
150
|
+
element.note_attributes_initialised(@is_realising)
|
151
|
+
else
|
152
|
+
if klasses[0].persisted? then
|
153
|
+
@attributeName.each_index do |i|
|
154
|
+
if @attributeName[i] == klasses[0].persisted?.to_s then
|
155
|
+
existing_element = Xampl.find_known(klasses[0], @attributeValue[i])
|
156
|
+
if existing_element then
|
157
|
+
# so we've found the element. Now what??? We can do several
|
158
|
+
# reasonable things:
|
159
|
+
#
|
160
|
+
# 1) continue parsing into the found element
|
161
|
+
# 2) simply return the found element
|
162
|
+
# 3) replace the found element with the new element
|
163
|
+
#
|
164
|
+
# The first one is dubious, so we won't.
|
165
|
+
# The second and third option both make complete sense
|
166
|
+
#
|
167
|
+
# We are going to do the second
|
168
|
+
#
|
169
|
+
# BTW, 'existing element' means a representation of this element already in memory
|
170
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
171
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
172
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
173
|
+
# puts "FOUND AN EXISTING THING... #{ klasses[0] } #{ @attributeValue[i] }"
|
174
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
175
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
176
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
177
|
+
# caller(0).each { | trace | puts " #{trace}"}
|
178
|
+
# existing_element.reset_contents
|
179
|
+
# element = existing_element
|
180
|
+
# existing_element = nil
|
181
|
+
# puts "#{File.basename(__FILE__)} #{__LINE__} EXISTING ELEMENT: #{ existing_element }"
|
182
|
+
# puts "#{File.basename(__FILE__)} #{__LINE__} WOW, must handle the existing element correctly"
|
183
|
+
element = existing_element #TODO -- IS THIS RIGHT????????????????????????
|
184
|
+
end
|
185
|
+
unless element then
|
186
|
+
element = klasses[0].new
|
187
|
+
requires_caching = @recovering
|
188
|
+
# puts "#{File.basename(__FILE__)} #{__LINE__} WOW, what about recovering????"
|
189
|
+
#TODO -- IS THIS RIGHT????????????????????????
|
190
|
+
requires_caching = true #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
191
|
+
unless @recovering then
|
192
|
+
element.force_load if parent
|
193
|
+
end
|
194
|
+
element.note_created(@is_realising)
|
195
|
+
end
|
196
|
+
|
197
|
+
break
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
unless element then
|
203
|
+
element = klasses[0].new
|
204
|
+
element.note_created(@is_realising)
|
205
|
+
end
|
206
|
+
|
207
|
+
element.note_initialise_attributes_with(@attributeName, @attributeNamespace, @attributeValue, @is_realising)
|
208
|
+
element.init_attributes(@attributeName, @attributeNamespace, @attributeValue)
|
209
|
+
element.note_attributes_initialised(@is_realising)
|
210
|
+
|
211
|
+
if requires_caching and element and element.persist_required then
|
212
|
+
# puts "ELEMENT: #{element}, #{element.class.name}"
|
213
|
+
Xampl.cache(element)
|
214
|
+
# found = Xampl.find_known(element.class, element.get_the_index)
|
215
|
+
# puts "OK? #{found == element} found: #{found}, element: #{element}"
|
216
|
+
# puts "=============================================================================="
|
217
|
+
end
|
218
|
+
|
219
|
+
#element = element.note_add_to_parent(parent, @is_realising)
|
220
|
+
#element.append_to(parent) if parent
|
221
|
+
end
|
222
|
+
|
223
|
+
while not endDocument?
|
224
|
+
case nextEvent
|
225
|
+
when START_DOCUMENT
|
226
|
+
return element if @recovering
|
227
|
+
return existing_element || element
|
228
|
+
when END_DOCUMENT
|
229
|
+
return element if @recovering
|
230
|
+
return existing_element || element
|
231
|
+
when START_ELEMENT
|
232
|
+
child, ignore_child = parse_element(element)
|
233
|
+
unless ignore_child then
|
234
|
+
case child
|
235
|
+
when XamplObject then
|
236
|
+
child = child.note_add_to_parent(element, @is_realising) if child
|
237
|
+
child = element.note_add_child(child, @is_realising) if element
|
238
|
+
child.append_to(element) if element and child
|
239
|
+
when XMLText then
|
240
|
+
puts "UNRECOGNISED Well-formed XML: #{child.to_s[0..25]}..."
|
241
|
+
else
|
242
|
+
puts "WHAT IS THIS??? #{child.class.name}"
|
243
|
+
end
|
244
|
+
# if child.kind_of? XamplObject then
|
245
|
+
# child = child.note_add_to_parent(element, @is_realising) if child
|
246
|
+
# child = element.note_add_child(child, @is_realising) if element
|
247
|
+
# child.append_to(element) if element and child
|
248
|
+
# else
|
249
|
+
# puts "WHAT IS THIS??? #{child.class.name}"
|
250
|
+
# end
|
251
|
+
end
|
252
|
+
when END_ELEMENT
|
253
|
+
element = element.note_closed(@is_realising)
|
254
|
+
return element if @recovering
|
255
|
+
return existing_element || element
|
256
|
+
when TEXT, CDATA_SECTION, ENTITY_REF
|
257
|
+
if element.has_mixed_content then
|
258
|
+
the_text = element.note_adding_text_content(@text, @is_realising)
|
259
|
+
# element.add_content(the_text, @tokenise_content)
|
260
|
+
element << the_text
|
261
|
+
# puts "#{__LINE__ }:: add_content [#{the_text}]"
|
262
|
+
else
|
263
|
+
unless whitespace? then
|
264
|
+
the_text = element.note_adding_text_content(@text, @is_realising)
|
265
|
+
# 16 Mar 2007 -- this was making preformatted text content impossible
|
266
|
+
# element.add_content(the_text, @tokenise_content)
|
267
|
+
element.add_content(the_text, false)
|
268
|
+
# puts "#{__LINE__ }:: add_content [#{the_text}] --> [#{element.content}]"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
return element if @recovering
|
275
|
+
return existing_element || element
|
276
|
+
end
|
277
|
+
|
278
|
+
def next_interesting_event
|
279
|
+
if (endDocument?) then
|
280
|
+
return Xampl_PP::END_DOCUMENT
|
281
|
+
end
|
282
|
+
|
283
|
+
boring = true
|
284
|
+
while boring do
|
285
|
+
event = nextEvent
|
286
|
+
case event
|
287
|
+
when Xampl_PP::START_DOCUMENT
|
288
|
+
boring = true
|
289
|
+
when Xampl_PP::END_DOCUMENT
|
290
|
+
boring = false
|
291
|
+
when Xampl_PP::START_ELEMENT
|
292
|
+
boring = false
|
293
|
+
when Xampl_PP::END_ELEMENT
|
294
|
+
boring = false
|
295
|
+
when Xampl_PP::TEXT
|
296
|
+
boring = false
|
297
|
+
when Xampl_PP::CDATA_SECTION
|
298
|
+
boring = false
|
299
|
+
when Xampl_PP::ENTITY_REF
|
300
|
+
boring = false
|
301
|
+
when Xampl_PP::IGNORABLE_WHITESPACE
|
302
|
+
boring = true
|
303
|
+
when Xampl_PP::PROCESSING_INSTRUCTION
|
304
|
+
boring = true
|
305
|
+
when Xampl_PP::COMMENT
|
306
|
+
boring = true
|
307
|
+
when Xampl_PP::DOCTYPE
|
308
|
+
boring = true
|
309
|
+
end
|
310
|
+
end
|
311
|
+
return event
|
312
|
+
end
|
313
|
+
|
314
|
+
def attributeCount
|
315
|
+
return @attributeName.length
|
316
|
+
end
|
317
|
+
|
318
|
+
def attributeName(i)
|
319
|
+
return @attributeName[i]
|
320
|
+
end
|
321
|
+
|
322
|
+
def attributeNamespace(i)
|
323
|
+
return @attributeNamespace[i]
|
324
|
+
end
|
325
|
+
|
326
|
+
def attributeQName(i)
|
327
|
+
return @attributeQName[i]
|
328
|
+
end
|
329
|
+
|
330
|
+
def attributePrefix(i)
|
331
|
+
return @attributePrefix[i]
|
332
|
+
end
|
333
|
+
|
334
|
+
def attributeValue(i)
|
335
|
+
return @attributeValue[i]
|
336
|
+
end
|
337
|
+
|
338
|
+
def depth
|
339
|
+
return depth
|
340
|
+
end
|
341
|
+
|
342
|
+
def line
|
343
|
+
return line
|
344
|
+
end
|
345
|
+
|
346
|
+
def column
|
347
|
+
return column
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
data/lib/xamplr/from-xml.rb
CHANGED
@@ -1,19 +1,28 @@
|
|
1
|
-
require
|
1
|
+
require 'libxml'
|
2
2
|
|
3
3
|
module Xampl
|
4
4
|
|
5
|
-
class FromXML
|
5
|
+
class FromXML
|
6
6
|
|
7
7
|
attr :checkWellFormed, false
|
8
8
|
attr :is_realising, false
|
9
9
|
attr :tokenise_content, false
|
10
10
|
|
11
|
+
@reader = nil
|
12
|
+
|
11
13
|
@@by_tag = {}
|
12
14
|
@@by_ns_tag = {}
|
13
15
|
|
14
16
|
def initialize(recovering=false)
|
15
|
-
super()
|
16
17
|
@recovering = recovering
|
18
|
+
|
19
|
+
@attribute_name = Array.new(32)
|
20
|
+
@attribute_namespace = Array.new(32)
|
21
|
+
@attribute_value = Array.new(32)
|
22
|
+
|
23
|
+
@insert_end_element = false
|
24
|
+
@faking_an_end_element = false
|
25
|
+
@just_opened_an_element = false
|
17
26
|
end
|
18
27
|
|
19
28
|
def FromXML.reset_registry
|
@@ -41,31 +50,39 @@ module Xampl
|
|
41
50
|
end
|
42
51
|
|
43
52
|
def resolve(name)
|
53
|
+
#TODO -- ???
|
44
54
|
return name
|
45
55
|
end
|
46
56
|
|
47
57
|
def setup_parse(filename, tokenise_content=true, is_realising=false)
|
48
|
-
@processNamespace = true
|
49
|
-
@reportNamespaceAttributes = false
|
50
|
-
@checkWellFormed = false
|
51
58
|
@resolver = self
|
52
59
|
|
53
60
|
@is_realising = is_realising
|
54
61
|
@tokenise_content = tokenise_content
|
55
62
|
|
56
|
-
|
63
|
+
@reader = LibXML::XML::Reader.file(filename,
|
64
|
+
:options => LibXML::XML::Parser::Options::NOENT |
|
65
|
+
LibXML::XML::Parser::Options::NONET |
|
66
|
+
LibXML::XML::Parser::Options::NOCDATA |
|
67
|
+
LibXML::XML::Parser::Options::DTDATTR |
|
68
|
+
LibXML::XML::Parser::Options::COMPACT)
|
69
|
+
#TODO CLOSE THIS THING!!
|
57
70
|
end
|
58
71
|
|
59
72
|
def setup_parse_string(string, tokenise_content=true, is_realising=false)
|
60
|
-
@processNamespace = true
|
61
|
-
@reportNamespaceAttributes = false
|
62
|
-
@checkWellFormed = false
|
63
73
|
@resolver = self
|
64
74
|
|
65
75
|
@is_realising = is_realising
|
66
76
|
@tokenise_content = tokenise_content
|
67
77
|
|
68
|
-
setInput(string)
|
78
|
+
# setInput(string)
|
79
|
+
@reader = LibXML::XML::Reader.string(string,
|
80
|
+
:options => LibXML::XML::Parser::Options::NOENT |
|
81
|
+
LibXML::XML::Parser::Options::NONET |
|
82
|
+
LibXML::XML::Parser::Options::NOCDATA |
|
83
|
+
LibXML::XML::Parser::Options::DTDATTR |
|
84
|
+
LibXML::XML::Parser::Options::COMPACT)
|
85
|
+
#TODO CLOSE THIS THING!!
|
69
86
|
end
|
70
87
|
|
71
88
|
def parse(filename, tokenise_content=true, is_realising=false)
|
@@ -104,247 +121,319 @@ module Xampl
|
|
104
121
|
end
|
105
122
|
|
106
123
|
def parse_element(parent=nil, target=nil)
|
107
|
-
|
124
|
+
find_the_first_element
|
125
|
+
return unless start_element?
|
126
|
+
|
127
|
+
namespace = @reader.namespace_uri
|
128
|
+
name = @reader.local_name
|
108
129
|
|
109
130
|
existing_element = nil
|
110
131
|
element = nil
|
111
132
|
|
112
133
|
requires_caching = false
|
113
134
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
if (1 < klasses.size) then
|
127
|
-
raise XamplException.new("there is more than one '#{@name}' tag in namespace '#{@namespace}'\nplease report this error")
|
128
|
-
end
|
129
|
-
else
|
130
|
-
klasses = FromXML.registered(@name)
|
131
|
-
if (0 == klasses.size) then
|
132
|
-
raise XamplException.new("do not recognise tag '#{@name}' (no namespace specified)")
|
133
|
-
end
|
134
|
-
if (1 < klasses.size) then
|
135
|
-
raise XamplException.new("there is more than one '#{@name}' tag (no namespace specified)")
|
136
|
-
end
|
135
|
+
build_attribute_arrays
|
136
|
+
|
137
|
+
if ((nil != namespace) and (0 < namespace.size)) then
|
138
|
+
klass_name = "{#{namespace}}#{name}"
|
139
|
+
klasses = FromXML.registered(klass_name)
|
140
|
+
if (0 == klasses.size) then
|
141
|
+
xml_text = XMLText.new
|
142
|
+
xml_text.build(self)
|
143
|
+
xml_text = parent.note_adding_text_content(xml_text, @is_realising)
|
144
|
+
parent.add_content(xml_text, @tokenise_content) if xml_text
|
145
|
+
return xml_text, false
|
137
146
|
end
|
147
|
+
if (1 < klasses.size) then
|
148
|
+
raise XamplException.new("there is more than one '#{name}' tag in namespace '#{namespace}'\nplease report this error")
|
149
|
+
end
|
150
|
+
else
|
151
|
+
klasses = FromXML.registered(name)
|
152
|
+
if (0 == klasses.size) then
|
153
|
+
raise XamplException.new("do not recognise tag '#{name}' (no namespace specified)")
|
154
|
+
end
|
155
|
+
if (1 < klasses.size) then
|
156
|
+
raise XamplException.new("there is more than one '#{name}' tag (no namespace specified)")
|
157
|
+
end
|
158
|
+
end
|
138
159
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
end
|
160
|
+
unless @is_realising then
|
161
|
+
@attribute_value.size.times do |i|
|
162
|
+
FromXML.tokenise_string @attribute_value[i]
|
143
163
|
end
|
164
|
+
end
|
144
165
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
# puts "#{File.basename(__FILE__)} #{__LINE__} EXISTING ELEMENT: #{ existing_element }"
|
182
|
-
# puts "#{File.basename(__FILE__)} #{__LINE__} WOW, must handle the existing element correctly"
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
166
|
+
if target then
|
167
|
+
element = target
|
168
|
+
target.load_needed = false
|
169
|
+
target = nil
|
170
|
+
element.init_attributes(@attribute_name, @attribute_namespace, @attribute_value)
|
171
|
+
element.note_attributes_initialised(@is_realising)
|
172
|
+
else
|
173
|
+
if klasses[0].persisted? then
|
174
|
+
@attribute_name.each_index do |i|
|
175
|
+
if @attribute_name[i] == klasses[0].persisted?.to_s then
|
176
|
+
existing_element = Xampl.find_known(klasses[0], @attribute_value[i])
|
177
|
+
if existing_element then
|
178
|
+
# so we've found the element. Now what??? We can do several
|
179
|
+
# reasonable things:
|
180
|
+
#
|
181
|
+
# 1) continue parsing into the found element
|
182
|
+
# 2) simply return the found element
|
183
|
+
# 3) replace the found element with the new element
|
184
|
+
#
|
185
|
+
# The first one is dubious, so we won't.
|
186
|
+
# The second and third option both make complete sense
|
187
|
+
#
|
188
|
+
# We are going to do the second
|
189
|
+
#
|
190
|
+
# BTW, 'existing element' means a representation of this element already in memory
|
191
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
192
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
193
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
194
|
+
# puts "FOUND AN EXISTING THING... #{ klasses[0] } #{ @attribute_value[i] }"
|
195
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
196
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
197
|
+
# puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
198
|
+
# caller(0).each { | trace | puts " #{trace}"}
|
199
|
+
# existing_element.reset_contents
|
200
|
+
# element = existing_element
|
201
|
+
# existing_element = nil
|
202
|
+
# puts "#{File.basename(__FILE__)} #{__LINE__} EXISTING ELEMENT: #{ existing_element }"
|
203
|
+
# puts "#{File.basename(__FILE__)} #{__LINE__} WOW, must handle the existing element correctly"
|
204
|
+
element = existing_element #TODO -- IS THIS RIGHT????????????????????????
|
205
|
+
end
|
206
|
+
unless element then
|
207
|
+
element = klasses[0].new
|
208
|
+
requires_caching = @recovering
|
188
209
|
# puts "#{File.basename(__FILE__)} #{__LINE__} WOW, what about recovering????"
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
end
|
194
|
-
element.note_created(@is_realising)
|
210
|
+
#TODO -- IS THIS RIGHT????????????????????????
|
211
|
+
requires_caching = true #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
212
|
+
unless @recovering then
|
213
|
+
element.force_load if parent
|
195
214
|
end
|
196
|
-
|
197
|
-
break
|
215
|
+
element.note_created(@is_realising)
|
198
216
|
end
|
199
|
-
end
|
200
|
-
end
|
201
217
|
|
202
|
-
|
203
|
-
|
204
|
-
element.note_created(@is_realising)
|
218
|
+
break
|
219
|
+
end
|
205
220
|
end
|
221
|
+
end
|
206
222
|
|
207
|
-
|
208
|
-
element
|
209
|
-
element.
|
223
|
+
unless element then
|
224
|
+
element = klasses[0].new
|
225
|
+
element.note_created(@is_realising)
|
226
|
+
end
|
210
227
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
# found = Xampl.find_known(element.class, element.get_the_index)
|
215
|
-
# puts "OK? #{found == element} found: #{found}, element: #{element}"
|
216
|
-
# puts "=============================================================================="
|
217
|
-
end
|
228
|
+
element.note_initialise_attributes_with(@attribute_name, @attribute_namespace, @attribute_value, @is_realising)
|
229
|
+
element.init_attributes(@attribute_name, @attribute_namespace, @attribute_value)
|
230
|
+
element.note_attributes_initialised(@is_realising)
|
218
231
|
|
219
|
-
|
220
|
-
|
232
|
+
if requires_caching and element and element.persist_required then
|
233
|
+
Xampl.cache(element)
|
221
234
|
end
|
222
235
|
|
223
|
-
|
224
|
-
|
236
|
+
#element = element.note_add_to_parent(parent, @is_realising)
|
237
|
+
#element.append_to(parent) if parent
|
238
|
+
end
|
239
|
+
|
240
|
+
while next_reader_event
|
241
|
+
case current_node_type
|
242
|
+
|
243
|
+
=begin
|
244
|
+
TODO -- can these ever happen?
|
225
245
|
when START_DOCUMENT
|
226
246
|
return element if @recovering
|
227
247
|
return existing_element || element
|
228
248
|
when END_DOCUMENT
|
229
249
|
return element if @recovering
|
230
250
|
return existing_element || element
|
231
|
-
|
251
|
+
|
252
|
+
=end
|
253
|
+
|
254
|
+
when LibXML::XML::Reader::TYPE_ELEMENT
|
232
255
|
child, ignore_child = parse_element(element)
|
256
|
+
|
233
257
|
unless ignore_child then
|
234
258
|
case child
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
259
|
+
when XamplObject then
|
260
|
+
child = child.note_add_to_parent(element, @is_realising) if child
|
261
|
+
child = element.note_add_child(child, @is_realising) if element
|
262
|
+
child.append_to(element) if element and child
|
263
|
+
when XMLText then
|
264
|
+
puts "UNRECOGNISED Well-formed XML: #{child.to_s[0..25]}..."
|
265
|
+
else
|
266
|
+
puts "WHAT IS THIS??? #{child.class.name}"
|
243
267
|
end
|
244
|
-
# if child.kind_of? XamplObject then
|
245
|
-
# child = child.note_add_to_parent(element, @is_realising) if child
|
246
|
-
# child = element.note_add_child(child, @is_realising) if element
|
247
|
-
# child.append_to(element) if element and child
|
248
|
-
# else
|
249
|
-
# puts "WHAT IS THIS??? #{child.class.name}"
|
250
|
-
# end
|
251
268
|
end
|
252
|
-
when
|
269
|
+
when LibXML::XML::Reader::TYPE_END_ELEMENT
|
253
270
|
element = element.note_closed(@is_realising)
|
254
271
|
return element if @recovering
|
255
272
|
return existing_element || element
|
256
|
-
when
|
273
|
+
when LibXML::XML::Reader::TYPE_TEXT, LibXML::XML::Reader::TYPE_CDATA, LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE, LibXML::XML::Reader::TYPE_ENTITY_REFERENCE
|
257
274
|
if element.has_mixed_content then
|
258
|
-
|
259
|
-
|
275
|
+
text = @reader.read_string
|
276
|
+
the_text = element.note_adding_text_content(text, @is_realising)
|
260
277
|
element << the_text
|
261
|
-
# puts "#{__LINE__ }:: add_content [#{the_text}]"
|
262
278
|
else
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
# element.add_content(the_text, @tokenise_content)
|
267
|
-
element.add_content(the_text, false)
|
268
|
-
# puts "#{__LINE__ }:: add_content [#{the_text}] --> [#{element.content}]"
|
269
|
-
end
|
279
|
+
text = @reader.read_string
|
280
|
+
the_text = element.note_adding_text_content(text, @is_realising)
|
281
|
+
element.add_content(the_text, false)
|
270
282
|
end
|
271
|
-
|
283
|
+
else
|
272
284
|
end
|
273
285
|
end
|
286
|
+
|
274
287
|
return element if @recovering
|
275
288
|
return existing_element || element
|
276
289
|
end
|
277
290
|
|
278
|
-
def
|
279
|
-
if
|
280
|
-
|
291
|
+
def current_node_type
|
292
|
+
if @faking_an_end_element then
|
293
|
+
LibXML::XML::Reader::TYPE_END_ELEMENT
|
294
|
+
else
|
295
|
+
@reader.node_type
|
281
296
|
end
|
297
|
+
end
|
282
298
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
299
|
+
=begin
|
300
|
+
def describe_current_element_type()
|
301
|
+
case @reader.node_type
|
302
|
+
when LibXML::XML::Reader::TYPE_ATTRIBUTE
|
303
|
+
puts "ATTRIBUTE"
|
304
|
+
when LibXML::XML::Reader::TYPE_DOCUMENT
|
305
|
+
puts "DOCUMENT"
|
306
|
+
when LibXML::XML::Reader::TYPE_ELEMENT
|
307
|
+
attribute_count = @reader.attribute_count
|
308
|
+
puts "ELEMENT #{ @reader.local_name }, ns: #{ @reader.namespace_uri }, #attributes: #{ attribute_count }, depth: #{ @reader.depth }"
|
309
|
+
puts " FAKING END ELEMENT" if @faking_an_end_element
|
310
|
+
when LibXML::XML::Reader::TYPE_END_ELEMENT
|
311
|
+
puts "END ELEMENT"
|
312
|
+
when LibXML::XML::Reader::TYPE_TEXT
|
313
|
+
puts "TEXT [[#{ @reader.read_string }]]"
|
314
|
+
when LibXML::XML::Reader::TYPE_CDATA
|
315
|
+
puts "CDATA [[#{ @reader.read_string }]]"
|
316
|
+
when LibXML::XML::Reader::TYPE_SIGNIFICANT_WHITESPACE
|
317
|
+
puts "SIGNIFICANT white space [[#{ @reader.read_string }]]"
|
318
|
+
when LibXML::XML::Reader::TYPE_ENTITY_REFERENCE
|
319
|
+
puts "entity ref"
|
320
|
+
when LibXML::XML::Reader::TYPE_WHITESPACE
|
321
|
+
puts "whitespace"
|
322
|
+
when LibXML::XML::Reader::TYPE_PROCESSING_INSTRUCTION
|
323
|
+
puts "processing instruction"
|
324
|
+
when LibXML::XML::Reader::TYPE_COMMENT
|
325
|
+
puts "comment"
|
326
|
+
when LibXML::XML::Reader::TYPE_DOCUMENT_TYPE
|
327
|
+
puts "doc type"
|
328
|
+
|
329
|
+
when LibXML::XML::Reader::TYPE_XML_DECLARATION
|
330
|
+
puts "xml decl"
|
331
|
+
when LibXML::XML::Reader::TYPE_NONE
|
332
|
+
puts "NONE!!"
|
333
|
+
when LibXML::XML::Reader::TYPE_NOTATION
|
334
|
+
puts "notifiation"
|
335
|
+
when LibXML::XML::Reader::TYPE_DOCUMENT_FRAGMENT
|
336
|
+
puts "doc fragment"
|
337
|
+
when LibXML::XML::Reader::TYPE_ENTITY
|
338
|
+
puts "entity"
|
339
|
+
when LibXML::XML::Reader::TYPE_END_ENTITY
|
340
|
+
puts "end entity"
|
341
|
+
else
|
342
|
+
puts "UNKNOWN: #{@reader.node_type}"
|
310
343
|
end
|
311
|
-
return event
|
312
344
|
end
|
345
|
+
=end
|
313
346
|
|
314
|
-
def
|
315
|
-
|
347
|
+
def next_reader_event
|
348
|
+
if @insert_end_element then
|
349
|
+
@faking_an_end_element = true
|
350
|
+
@insert_end_element = false
|
351
|
+
return
|
352
|
+
end
|
353
|
+
|
354
|
+
@faking_an_end_element = false
|
355
|
+
|
356
|
+
#describe_current_element_type
|
357
|
+
|
358
|
+
okay = @reader.read
|
359
|
+
|
360
|
+
@just_opened_an_element = start_element?
|
361
|
+
@insert_end_element = (@just_opened_an_element and @reader.empty_element?)
|
362
|
+
|
363
|
+
#describe_current_element_type
|
364
|
+
|
365
|
+
okay
|
316
366
|
end
|
317
367
|
|
318
|
-
def
|
319
|
-
|
368
|
+
def start_element?
|
369
|
+
current_node_type == LibXML::XML::Reader::TYPE_ELEMENT
|
320
370
|
end
|
321
371
|
|
322
|
-
def
|
323
|
-
|
372
|
+
def whitespace?
|
373
|
+
current_note_type == LibXML::XML::Reader::TYPE_WHITESPACE
|
374
|
+
end
|
375
|
+
|
376
|
+
def find_the_first_element
|
377
|
+
while true do
|
378
|
+
break if start_element?
|
379
|
+
break unless next_reader_event
|
380
|
+
end
|
381
|
+
@just_opened_an_element = start_element?
|
324
382
|
end
|
325
383
|
|
326
|
-
def
|
327
|
-
|
384
|
+
def build_attribute_arrays
|
385
|
+
|
386
|
+
@attribute_name.clear
|
387
|
+
@attribute_namespace.clear
|
388
|
+
@attribute_value.clear
|
389
|
+
|
390
|
+
return unless LibXML::XML::Reader::TYPE_ELEMENT == current_node_type
|
391
|
+
|
392
|
+
if @reader.has_attributes? then
|
393
|
+
attribute_count = @reader.attribute_count
|
394
|
+
@reader.move_to_first_attribute
|
395
|
+
attribute_count.times do | i |
|
396
|
+
if @reader.namespace_declaration? then
|
397
|
+
@reader.move_to_next_attribute
|
398
|
+
next
|
399
|
+
end
|
400
|
+
|
401
|
+
@attribute_name << @reader.local_name
|
402
|
+
@attribute_namespace << @reader.namespace_uri
|
403
|
+
@attribute_value << @reader.value
|
404
|
+
|
405
|
+
@reader.move_to_next_attribute
|
406
|
+
end
|
407
|
+
end
|
328
408
|
end
|
329
409
|
|
330
|
-
def
|
331
|
-
return @
|
410
|
+
def attributeCount
|
411
|
+
return @attribute_name.length
|
412
|
+
end
|
413
|
+
|
414
|
+
def attributeName(i)
|
415
|
+
return @attribute_name[i]
|
416
|
+
end
|
417
|
+
|
418
|
+
def attributeNamespace(i)
|
419
|
+
return @attribute_namespace[i]
|
332
420
|
end
|
333
421
|
|
334
422
|
def attributeValue(i)
|
335
|
-
return @
|
423
|
+
return @attribute_value[i]
|
336
424
|
end
|
337
425
|
|
338
426
|
def depth
|
339
|
-
return depth
|
427
|
+
return @reader.depth
|
340
428
|
end
|
341
429
|
|
342
430
|
def line
|
343
|
-
return
|
431
|
+
return @reader.line_number
|
344
432
|
end
|
345
433
|
|
346
434
|
def column
|
347
|
-
return
|
435
|
+
return @reader.column_number
|
348
436
|
end
|
349
437
|
end
|
438
|
+
|
350
439
|
end
|