josephholsten-rets4r 1.1.16 → 1.1.17
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/CHANGELOG +187 -3
- data/CONTRIBUTORS +2 -0
- data/NEWS +183 -0
- data/Rakefile +1 -1
- data/VERSION.yml +2 -2
- data/lib/rets4r.rb +2 -0
- data/lib/rets4r/client.rb +16 -15
- data/lib/rets4r/client/parsers/compact.rb +3 -2
- data/lib/rets4r/client/parsers/compact_nokogiri.rb +37 -11
- data/lib/rets4r/client/parsers/response_parser.rb +1 -5
- data/lib/rets4r/client/transaction.rb +3 -0
- data/lib/rets4r/core_ext/array/extract_options.rb +15 -0
- data/lib/rets4r/core_ext/class/attribute_accessors.rb +58 -0
- data/lib/rets4r/core_ext/hash/keys.rb +46 -0
- data/lib/rets4r/core_ext/hash/slice.rb +39 -0
- data/lib/rets4r/listing_mapper.rb +17 -0
- data/lib/rets4r/listing_service.rb +35 -0
- data/lib/rets4r/loader.rb +4 -8
- data/test/compact_nokogiri_test.rb +18 -2
- data/test/data/1.5/count_only_compact.xml +3 -0
- data/test/data/1.5/search_compact_big.xml +136 -0
- data/test/data/listing_service.yml +36 -0
- data/test/listing_mapper_test.rb +112 -0
- data/test/test_helper.rb +12 -0
- data/test/test_parser.rb +3 -0
- metadata +25 -8
- data/lib/rets4r/client/metadataindex.rb +0 -82
- data/test/test_metadataindex.rb +0 -36
@@ -7,7 +7,8 @@ module RETS4R
|
|
7
7
|
class CompactDataParser
|
8
8
|
def parse_results(doc)
|
9
9
|
|
10
|
-
delimiter = doc.get_elements('/RETS/DELIMITER')[0]
|
10
|
+
delimiter = doc.get_elements('/RETS/DELIMITER')[0] &&
|
11
|
+
doc.get_elements('/RETS/DELIMITER')[0].attributes['value'].to_i.chr
|
11
12
|
columns = doc.get_elements('/RETS/COLUMNS')[0]
|
12
13
|
rows = doc.get_elements('/RETS/DATA')
|
13
14
|
|
@@ -16,7 +17,7 @@ module RETS4R
|
|
16
17
|
|
17
18
|
def parse_data(column_element, row_elements, delimiter = "\t")
|
18
19
|
|
19
|
-
column_names = column_element.
|
20
|
+
column_names = column_element.to_s.split(delimiter)
|
20
21
|
|
21
22
|
result = []
|
22
23
|
|
@@ -2,15 +2,28 @@ require 'rubygems'
|
|
2
2
|
require 'nokogiri'
|
3
3
|
module RETS4R
|
4
4
|
class Client
|
5
|
-
class CompactNokogiriParser
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
parser.
|
10
|
-
|
5
|
+
class CompactNokogiriParser
|
6
|
+
|
7
|
+
def initialize(io)
|
8
|
+
@doc = CompactDocument.new
|
9
|
+
@parser = Nokogiri::XML::SAX::Parser.new(@doc)
|
10
|
+
@io = io
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_a
|
14
|
+
@parser.parse(@io) if @doc.results.empty?
|
15
|
+
@doc.results
|
11
16
|
end
|
17
|
+
|
18
|
+
def each(&block)
|
19
|
+
@doc.proc = block.to_proc
|
20
|
+
@parser.parse(@io)
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
12
24
|
class CompactDocument < Nokogiri::XML::SAX::Document
|
13
25
|
attr_reader :results
|
26
|
+
attr_writer :proc
|
14
27
|
|
15
28
|
def initialize
|
16
29
|
@results = []
|
@@ -35,10 +48,7 @@ module RETS4R
|
|
35
48
|
@columns = @string.split(@delimiter)
|
36
49
|
when 'DATA'
|
37
50
|
@data_element = false
|
38
|
-
|
39
|
-
h[k] = v unless k.empty?
|
40
|
-
next h
|
41
|
-
end
|
51
|
+
handle_row
|
42
52
|
end
|
43
53
|
end
|
44
54
|
|
@@ -49,7 +59,23 @@ module RETS4R
|
|
49
59
|
@string << string
|
50
60
|
end
|
51
61
|
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def handle_row
|
65
|
+
data = make_hash
|
66
|
+
if @proc
|
67
|
+
@proc.call(data)
|
68
|
+
else
|
69
|
+
@results << data
|
70
|
+
end
|
71
|
+
end
|
72
|
+
def make_hash
|
73
|
+
@columns.zip(@string.split(@delimiter)).inject({}) do | h,(k,v) |
|
74
|
+
h[k] = v unless k.empty?
|
75
|
+
next h
|
76
|
+
end
|
77
|
+
end
|
52
78
|
end
|
53
79
|
end
|
54
80
|
end
|
55
|
-
end
|
81
|
+
end
|
@@ -61,10 +61,6 @@ module RETS4R
|
|
61
61
|
raise RETSException, 'No transaction body was returned!'
|
62
62
|
end
|
63
63
|
|
64
|
-
File.open('/tmp/meh', 'w') do |file|
|
65
|
-
file.write(xml)
|
66
|
-
end
|
67
|
-
|
68
64
|
doc = REXML::Document.new(xml)
|
69
65
|
|
70
66
|
root = doc.root
|
@@ -91,7 +87,7 @@ module RETS4R
|
|
91
87
|
|
92
88
|
def get_parser_by_name(name)
|
93
89
|
case name
|
94
|
-
when 'COMPACT'
|
90
|
+
when 'COMPACT', 'COMPACT-DECODED'
|
95
91
|
type = RETS4R::Client::CompactDataParser
|
96
92
|
else
|
97
93
|
raise "Invalid format #{name}"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# from ActiveSupport
|
2
|
+
class Array
|
3
|
+
# Extracts options from a set of arguments. Removes and returns the last
|
4
|
+
# element in the array if it's a hash, otherwise returns a blank hash.
|
5
|
+
#
|
6
|
+
# def options(*args)
|
7
|
+
# args.extract_options!
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# options(1, 2) # => {}
|
11
|
+
# options(1, 2, :a => :b) # => {:a=>:b}
|
12
|
+
def extract_options!
|
13
|
+
last.is_a?(::Hash) ? pop : {}
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rets4r/core_ext/array/extract_options'
|
2
|
+
# from ActiveSupport
|
3
|
+
|
4
|
+
# Extends the class object with class and instance accessors for class attributes,
|
5
|
+
# just like the native attr* accessors for instance attributes.
|
6
|
+
#
|
7
|
+
# class Person
|
8
|
+
# cattr_accessor :hair_colors
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# Person.hair_colors = [:brown, :black, :blonde, :red]
|
12
|
+
class Class
|
13
|
+
def cattr_reader(*syms)
|
14
|
+
syms.flatten.each do |sym|
|
15
|
+
next if sym.is_a?(Hash)
|
16
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
17
|
+
unless defined? @@#{sym} # unless defined? @@hair_colors
|
18
|
+
@@#{sym} = nil # @@hair_colors = nil
|
19
|
+
end # end
|
20
|
+
#
|
21
|
+
def self.#{sym} # def self.hair_colors
|
22
|
+
@@#{sym} # @@hair_colors
|
23
|
+
end # end
|
24
|
+
#
|
25
|
+
def #{sym} # def hair_colors
|
26
|
+
@@#{sym} # @@hair_colors
|
27
|
+
end # end
|
28
|
+
EOS
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def cattr_writer(*syms)
|
33
|
+
options = syms.extract_options!
|
34
|
+
syms.flatten.each do |sym|
|
35
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
36
|
+
unless defined? @@#{sym} # unless defined? @@hair_colors
|
37
|
+
@@#{sym} = nil # @@hair_colors = nil
|
38
|
+
end # end
|
39
|
+
#
|
40
|
+
def self.#{sym}=(obj) # def self.hair_colors=(obj)
|
41
|
+
@@#{sym} = obj # @@hair_colors = obj
|
42
|
+
end # end
|
43
|
+
#
|
44
|
+
#{" #
|
45
|
+
def #{sym}=(obj) # def hair_colors=(obj)
|
46
|
+
@@#{sym} = obj # @@hair_colors = obj
|
47
|
+
end # end
|
48
|
+
" unless options[:instance_writer] == false } # # instance writer above is generated unless options[:instance_writer] == false
|
49
|
+
EOS
|
50
|
+
self.send("#{sym}=", yield) if block_given?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def cattr_accessor(*syms, &blk)
|
55
|
+
cattr_reader(*syms)
|
56
|
+
cattr_writer(*syms, &blk)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# from ActiveSupport
|
2
|
+
class Hash
|
3
|
+
# Return a new hash with all keys converted to strings.
|
4
|
+
def stringify_keys
|
5
|
+
dup.stringify_keys!
|
6
|
+
end
|
7
|
+
|
8
|
+
# Destructively convert all keys to strings.
|
9
|
+
def stringify_keys!
|
10
|
+
keys.each do |key|
|
11
|
+
self[key.to_s] = delete(key)
|
12
|
+
end
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return a new hash with all keys converted to symbols, as long as
|
17
|
+
# they respond to +to_sym+.
|
18
|
+
def symbolize_keys
|
19
|
+
dup.symbolize_keys!
|
20
|
+
end
|
21
|
+
|
22
|
+
# Destructively convert all keys to symbols, as long as they respond
|
23
|
+
# to +to_sym+.
|
24
|
+
def symbolize_keys!
|
25
|
+
keys.each do |key|
|
26
|
+
self[(key.to_sym rescue key) || key] = delete(key)
|
27
|
+
end
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method :to_options, :symbolize_keys
|
32
|
+
alias_method :to_options!, :symbolize_keys!
|
33
|
+
|
34
|
+
# Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
|
35
|
+
# Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
|
36
|
+
# as keys, this will fail.
|
37
|
+
#
|
38
|
+
# ==== Examples
|
39
|
+
# { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
|
40
|
+
# { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
|
41
|
+
# { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
|
42
|
+
def assert_valid_keys(*valid_keys)
|
43
|
+
unknown_keys = keys - [valid_keys].flatten
|
44
|
+
raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# from ActiveSupport
|
2
|
+
class Hash
|
3
|
+
# Slice a hash to include only the given keys. This is useful for
|
4
|
+
# limiting an options hash to valid keys before passing to a method:
|
5
|
+
#
|
6
|
+
# def search(criteria = {})
|
7
|
+
# assert_valid_keys(:mass, :velocity, :time)
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# search(options.slice(:mass, :velocity, :time))
|
11
|
+
#
|
12
|
+
# If you have an array of keys you want to limit to, you should splat them:
|
13
|
+
#
|
14
|
+
# valid_keys = [:mass, :velocity, :time]
|
15
|
+
# search(options.slice(*valid_keys))
|
16
|
+
def slice(*keys)
|
17
|
+
keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
|
18
|
+
hash = self.class.new
|
19
|
+
keys.each { |k| hash[k] = self[k] if has_key?(k) }
|
20
|
+
hash
|
21
|
+
end
|
22
|
+
|
23
|
+
# Replaces the hash with only the given keys.
|
24
|
+
# Returns a hash contained the removed key/value pairs
|
25
|
+
# {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d =>4}
|
26
|
+
def slice!(*keys)
|
27
|
+
keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
|
28
|
+
omit = slice(*self.keys - keys)
|
29
|
+
hash = slice(*keys)
|
30
|
+
replace(hash)
|
31
|
+
omit
|
32
|
+
end
|
33
|
+
|
34
|
+
def extract!(*keys)
|
35
|
+
result = {}
|
36
|
+
keys.each {|key| result[key] = delete(key) }
|
37
|
+
result
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RETS4R
|
2
|
+
class ListingMapper
|
3
|
+
def initialize(params = {})
|
4
|
+
@select = params[:select] || ListingService.connection[:select]
|
5
|
+
end
|
6
|
+
def select
|
7
|
+
@select
|
8
|
+
end
|
9
|
+
def map(original)
|
10
|
+
listing = {}
|
11
|
+
@select.each_pair {|rets_key, record_key|
|
12
|
+
listing[record_key] = original[rets_key]
|
13
|
+
}
|
14
|
+
listing
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rets4r/core_ext/class/attribute_accessors'
|
2
|
+
require 'rets4r/core_ext/hash/keys'
|
3
|
+
require 'rets4r/core_ext/hash/slice'
|
4
|
+
|
5
|
+
module RETS4R
|
6
|
+
class ListingService
|
7
|
+
# RECORD_COUNT_ONLY=Librets::SearchRequest::RECORD_COUNT_ONLY
|
8
|
+
RECORD_COUNT_ONLY='fixme'
|
9
|
+
# Contains the listing service configurations - typically stored in
|
10
|
+
# config/listing_service.yml - as a Hash.
|
11
|
+
cattr_accessor :configurations, :instance_writer => false
|
12
|
+
cattr_accessor :env, :instance_writer => false
|
13
|
+
|
14
|
+
class << self
|
15
|
+
|
16
|
+
# Connection configuration for the specified environment, or the current
|
17
|
+
# environment if none is given.
|
18
|
+
def connection(spec = nil)
|
19
|
+
case spec
|
20
|
+
when nil
|
21
|
+
connection(RETS4R::ListingService.env)
|
22
|
+
when Symbol, String
|
23
|
+
if configuration = configurations[spec.to_s]
|
24
|
+
configuration.symbolize_keys
|
25
|
+
else
|
26
|
+
raise ArgumentError, "#{spec} listing service is not configured"
|
27
|
+
end
|
28
|
+
else
|
29
|
+
raise ArgumentError, "#{spec} listing service is not configured"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end # class << self
|
34
|
+
end
|
35
|
+
end
|
data/lib/rets4r/loader.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
module RETS4R
|
2
2
|
class Loader
|
3
|
-
def self.load(file)
|
4
|
-
parser = RETS4R::Client::CompactNokogiriParser.new
|
5
|
-
|
6
|
-
|
7
|
-
listings.each {|original|
|
8
|
-
yield original
|
9
|
-
}
|
3
|
+
def self.load(file, &block)
|
4
|
+
parser = RETS4R::Client::CompactNokogiriParser.new(file)
|
5
|
+
parser.each(&block)
|
10
6
|
end
|
11
7
|
end
|
12
|
-
end
|
8
|
+
end
|
@@ -6,14 +6,30 @@ require 'rets4r'
|
|
6
6
|
class CompactNokogiriTest < Test::Unit::TestCase
|
7
7
|
def test_should_do_stuff
|
8
8
|
file = File.expand_path(File.join('test', 'data', '1.5', 'search_compact.xml'))
|
9
|
-
listings = RETS4R::Client::CompactNokogiriParser.new
|
9
|
+
listings = RETS4R::Client::CompactNokogiriParser.new(open(file)).to_a
|
10
10
|
assert_equal({"Third"=>"Datum3", "Second"=>"Datum2", "First"=>"Datum1"}, listings[0])
|
11
11
|
assert_equal({"Third"=>"Datum6", "Second"=>"Datum5", "First"=>"Datum4"}, listings[1])
|
12
12
|
end
|
13
13
|
def test_should_handle_big_data
|
14
14
|
file = File.expand_path(File.join('test', 'data', '1.5', 'bad_compact.xml'))
|
15
|
-
listings = RETS4R::Client::CompactNokogiriParser.new
|
15
|
+
listings = RETS4R::Client::CompactNokogiriParser.new(open(file)).to_a
|
16
16
|
assert_equal 1, listings.length
|
17
17
|
assert_equal 79, listings.first.keys.length
|
18
18
|
end
|
19
|
+
def test_each_should_yield_between_results
|
20
|
+
file = File.expand_path(
|
21
|
+
File.join('test', 'data', '1.5', 'search_compact_big.xml'))
|
22
|
+
stat = File::Stat.new(file)
|
23
|
+
unless stat.size > stat.blksize
|
24
|
+
flunk "This test probably won't work on this machine.
|
25
|
+
It needs a test input file larger than the native block size."
|
26
|
+
end
|
27
|
+
stream = open(file)
|
28
|
+
positions = []
|
29
|
+
listings = RETS4R::Client::CompactNokogiriParser.new(stream).each do |row|
|
30
|
+
positions << stream.pos
|
31
|
+
end
|
32
|
+
assert positions.first < positions.last,
|
33
|
+
"data was yielded durring the reading of the stream"
|
34
|
+
end
|
19
35
|
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
<RETS ReplyCode="0" ReplyText="SUCCESS">
|
2
|
+
<COUNT Records="4"/>
|
3
|
+
<DELIMITER value="09" />
|
4
|
+
<COLUMNS> First Second Third </COLUMNS>
|
5
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
6
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
7
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
8
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
9
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
10
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
11
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
12
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
13
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
14
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
15
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
16
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
17
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
18
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
19
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
20
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
21
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
22
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
23
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
24
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
25
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
26
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
27
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
28
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
29
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
30
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
31
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
32
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
33
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
34
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
35
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
36
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
37
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
38
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
39
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
40
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
41
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
42
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
43
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
44
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
45
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
46
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
47
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
48
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
49
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
50
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
51
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
52
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
53
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
54
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
55
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
56
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
57
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
58
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
59
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
60
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
61
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
62
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
63
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
64
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
65
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
66
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
67
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
68
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
69
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
70
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
71
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
72
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
73
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
74
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
75
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
76
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
77
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
78
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
79
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
80
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
81
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
82
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
83
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
84
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
85
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
86
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
87
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
88
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
89
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
90
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
91
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
92
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
93
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
94
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
95
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
96
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
97
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
98
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
99
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
100
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
101
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
102
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
103
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
104
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
105
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
106
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
107
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
108
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
109
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
110
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
111
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
112
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
113
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
114
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
115
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
116
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
117
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
118
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
119
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
120
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
121
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
122
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
123
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
124
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
125
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
126
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
127
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
128
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
129
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
130
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
131
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
132
|
+
<DATA> Datum1 Datum2 Datum3</DATA>
|
133
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
134
|
+
<DATA> Datum4 Datum5 Datum6</DATA>
|
135
|
+
<MAXROWS/>
|
136
|
+
</RETS>
|