josephholsten-rets4r 1.1.16 → 1.1.17
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|