rspreadsheet 0.2.0 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.directory +4 -0
- data/.gitignore +2 -0
- data/.kateproject +4 -0
- data/.kateproject.d/notes.txt +0 -0
- data/DEVEL_BLOG.md +11 -5
- data/GUIDE.md +2 -2
- data/Guardfile +2 -2
- data/README.md +31 -14
- data/lib/class_extensions.rb +0 -11
- data/lib/rspreadsheet/cell.rb +118 -116
- data/lib/rspreadsheet/row.rb +339 -373
- data/lib/rspreadsheet/tools.rb +14 -5
- data/lib/rspreadsheet/version.rb +1 -1
- data/lib/rspreadsheet/worksheet.rb +24 -113
- data/lib/rspreadsheet/xml_tied.rb +234 -0
- data/lib/rspreadsheet.rb +1 -1
- data/reinstall2.sh +7 -0
- data/rspreadsheet.gemspec +6 -7
- data/spec/cell_spec.rb +187 -10
- data/spec/row_spec.rb +63 -7
- data/spec/rspreadsheet_spec.rb +32 -0
- data/spec/testfile1.ods +0 -0
- data/spec/worksheet_spec.rb +6 -4
- metadata +7 -5
- data/lib/rspreadsheet/.row.rb.kate-swp.bak +0 -0
- data/spec/xml_tied_array_spec.rb +0 -9
data/lib/rspreadsheet/tools.rb
CHANGED
@@ -14,9 +14,18 @@ module Tools
|
|
14
14
|
else
|
15
15
|
raise 'Wrong number of arguments'
|
16
16
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
|
18
|
+
## first possibility how to implement it
|
19
|
+
# colname=colname.rjust(3,'@')
|
20
|
+
# col = (colname[-1].ord-64)+(colname[-2].ord-64)*26+(colname[-3].ord-64)*26*26
|
21
|
+
|
22
|
+
## second possibility how to implement it
|
23
|
+
# col=(colname.to_i(36)-('A'*colname.size).to_i(36)).to_s(36).to_i(26)+('1'*colname.size).to_i(26)
|
24
|
+
|
25
|
+
## third possibility how to implement it (second one little shortened)
|
26
|
+
s=colname.size
|
27
|
+
col=(colname.to_i(36)-(36**s-1).div(3.5)).to_s(36).to_i(26)+(26**s-1)/25
|
28
|
+
|
20
29
|
row = rowname.to_i
|
21
30
|
return [row,col]
|
22
31
|
end
|
@@ -115,8 +124,8 @@ module Tools
|
|
115
124
|
node.attributes.get_attribute_ns(Tools.get_namespace(ns_prefix).href,key)
|
116
125
|
attr.remove! unless attr.nil?
|
117
126
|
end
|
118
|
-
def self.create_ns_node(nodename,
|
119
|
-
LibXML::XML::Node.new(nodename,
|
127
|
+
def self.create_ns_node(ns_prefix,nodename,value=nil)
|
128
|
+
LibXML::XML::Node.new(nodename,value, Tools.get_namespace(ns_prefix))
|
120
129
|
end
|
121
130
|
end
|
122
131
|
|
data/lib/rspreadsheet/version.rb
CHANGED
@@ -5,145 +5,53 @@ require 'rspreadsheet/tools'
|
|
5
5
|
module Rspreadsheet
|
6
6
|
|
7
7
|
class Worksheet
|
8
|
+
include XMLTiedArray
|
8
9
|
attr_accessor :name, :xmlnode
|
9
|
-
|
10
|
-
# def_delegators :nonemptycells
|
10
|
+
def subitem_xml_options; {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'} end
|
11
11
|
|
12
12
|
def initialize(xmlnode_or_sheet_name)
|
13
|
-
@
|
13
|
+
@itemcache = Hash.new #TODO: move to module XMLTiedArray
|
14
14
|
# set up the @xmlnode according to parameter
|
15
15
|
case xmlnode_or_sheet_name
|
16
16
|
when LibXML::XML::Node
|
17
17
|
@xmlnode = xmlnode_or_sheet_name
|
18
18
|
when String
|
19
|
-
@xmlnode =
|
20
|
-
|
21
|
-
@xmlnode .namespaces.namespace = ns
|
22
|
-
@xmlnode['table:name'] = xmlnode_or_sheet_name
|
19
|
+
@xmlnode = Tools.create_ns_node('table','table')
|
20
|
+
Tools.set_ns_attribute(@xmlnode,'table','name', xmlnode_or_sheet_name)
|
23
21
|
else raise 'Provide name or xml node to create a Worksheet object'
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
25
|
def rowxmlnode(rowi)
|
28
|
-
|
26
|
+
find_my_subnode_respect_repeated(rowi, {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
|
29
27
|
end
|
30
|
-
|
31
|
-
def
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def row_nonempty_cells_col_indexes(rowi)
|
36
|
-
arowxmlnode = rowxmlnode(rowi)
|
37
|
-
if arowxmlnode.nil?
|
38
|
-
[]
|
39
|
-
else
|
40
|
-
find_nonempty_subnode_indexes(arowxmlnode, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
|
41
|
-
end
|
28
|
+
|
29
|
+
def first_unused_row_index
|
30
|
+
find_first_unused_index_respect_repeated({:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
|
42
31
|
end
|
43
32
|
|
44
|
-
def
|
45
|
-
|
46
|
-
if arowxmlnode.nil?
|
47
|
-
nil
|
48
|
-
else
|
49
|
-
find_subnode_respect_repeated(arowxmlnode, coli, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def cellrange(coli)
|
54
|
-
find_subnode_range_respect_repeated(@xmlnode, rowi, {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
|
33
|
+
def insert_row_above(arowi)
|
34
|
+
insert_subitem_before(arowi)
|
55
35
|
end
|
56
36
|
|
57
|
-
def
|
58
|
-
|
37
|
+
def insert_cell_before(arowi,acoli)
|
38
|
+
detach_row_in_xml(arowi)
|
39
|
+
rows(arowi).insert_subitem_before(acoli)
|
59
40
|
end
|
60
41
|
|
61
42
|
def detach_row_in_xml(rowi)
|
62
|
-
return
|
63
|
-
end
|
64
|
-
def detach_cell_in_xml(rowi,coli)
|
65
|
-
rownode = detach_row_in_xml(rowi)
|
66
|
-
return detach_subnode_respect_repeated(rownode, coli, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
|
43
|
+
return detach_my_subnode_respect_repeated(rowi, {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
|
67
44
|
end
|
68
45
|
|
69
|
-
def
|
70
|
-
|
71
|
-
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
72
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
73
|
-
oldindex = index
|
74
|
-
index = index+repeated
|
75
|
-
if index>= aindex # found the node, now do the detachement
|
76
|
-
ranges = [oldindex+1..aindex-1,aindex..aindex,aindex+1..index].reject {|range| range.size<1}
|
77
|
-
ranges.each do |range|
|
78
|
-
newnode = node.copy(true)
|
79
|
-
Tools.set_ns_attribute(newnode,'table',options[:xml_repeated_attribute],range.size,1)
|
80
|
-
node.prev = newnode
|
81
|
-
end
|
82
|
-
node.remove!
|
83
|
-
return find_subnode_respect_repeated(axmlnode, aindex, options)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
# add outbound xmlnode
|
87
|
-
[index+1..aindex-1,aindex..aindex].reject {|range| range.size<1}.each do |range|
|
88
|
-
node = LibXML::XML::Node.new(options[:xml_items_node_name],nil, Tools.get_namespace('table'))
|
89
|
-
Tools.set_ns_attribute(node,'table',options[:xml_repeated_attribute],range.size, 1)
|
90
|
-
axmlnode << node
|
91
|
-
end
|
92
|
-
find_subnode_respect_repeated(axmlnode, aindex, options)
|
93
|
-
end
|
94
|
-
|
95
|
-
def find_subnode_respect_repeated(axmlnode, aindex, options)
|
96
|
-
index = 0
|
97
|
-
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
98
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
99
|
-
index = index+repeated
|
100
|
-
return node if index>= aindex
|
101
|
-
end
|
102
|
-
return nil
|
103
|
-
end
|
104
|
-
def find_subnode_range_respect_repeated(axmlnode, aindex, options)
|
105
|
-
index = 0
|
106
|
-
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
107
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
108
|
-
if index+repeated >= aindex
|
109
|
-
return (index+1..index+repeated)
|
110
|
-
else
|
111
|
-
index = index+repeated
|
112
|
-
end
|
113
|
-
end
|
114
|
-
return (index+1..Float::INFINITY)
|
46
|
+
def nonemptycells
|
47
|
+
used_rows_range.collect{ |rowi| rows(rowi).nonemptycells }.flatten
|
115
48
|
end
|
116
49
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
122
|
-
index = index + repeated
|
123
|
-
if !(node.content.nil? or node.content.empty? or node.content =='') and (repeated==1)
|
124
|
-
result << index
|
125
|
-
end
|
126
|
-
end
|
127
|
-
return result
|
128
|
-
end
|
129
|
-
def find_first_unused_index_respect_repeated(axmlnode, options)
|
130
|
-
index = 0
|
131
|
-
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
132
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
133
|
-
index = index+repeated
|
134
|
-
end
|
135
|
-
return index+1
|
136
|
-
end
|
50
|
+
# rozšíření XMLTiedArray
|
51
|
+
def rows(rowi); subitem(rowi) end
|
52
|
+
def prepare_subitem(rowi); Row.new(self,rowi) end
|
53
|
+
def rowcache; @itemcache end
|
137
54
|
|
138
|
-
def cells(r,c)
|
139
|
-
rows(r).andand.cells(c)
|
140
|
-
end
|
141
|
-
def nonemptycells
|
142
|
-
used_rows_range.collect{ |rowi| rows(rowi) }.collect { |row| row.nonemptycells }.flatten
|
143
|
-
end
|
144
|
-
def rows(rowi)
|
145
|
-
@rowcache[rowi] ||= Row.new(self,rowi) unless rowi<=0
|
146
|
-
end
|
147
55
|
## syntactic sugar follows
|
148
56
|
def [](r,c)
|
149
57
|
cells(r,c).andand.value
|
@@ -151,6 +59,9 @@ class Worksheet
|
|
151
59
|
def []=(r,c,avalue)
|
152
60
|
cells(r,c).andand.value=avalue
|
153
61
|
end
|
62
|
+
def cells(r,c)
|
63
|
+
rows(r).andand.cells(c)
|
64
|
+
end
|
154
65
|
# allows syntax like sheet.F15
|
155
66
|
def method_missing method_name, *args, &block
|
156
67
|
if method_name.to_s.match(/^([A-Z]{1,3})(\d{1,8})(=?)$/)
|
@@ -0,0 +1,234 @@
|
|
1
|
+
module Rspreadsheet
|
2
|
+
|
3
|
+
class XMLTied
|
4
|
+
def xml
|
5
|
+
xmlnode.to_s
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# abstrac class. All successort MUST implement: set_index,xml_options,parent,index
|
10
|
+
class XMLTiedItem < XMLTied
|
11
|
+
def mode
|
12
|
+
case
|
13
|
+
when xmlnode.nil? then :outbound
|
14
|
+
when repeated>1 then :repeated
|
15
|
+
else :regular
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def repeated; (Tools.get_ns_attribute_value(xmlnode, 'table', xml_repeated_attribute) || 1 ).to_i end
|
19
|
+
def repeated?; mode==:repeated || mode==:outbound end
|
20
|
+
alias :is_repeated? :repeated?
|
21
|
+
def xmlnode
|
22
|
+
parentnode = parent.xmlnode
|
23
|
+
if parentnode.nil?
|
24
|
+
nil
|
25
|
+
else
|
26
|
+
parent.find_my_subnode_respect_repeated(index, xml_options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def detach_if_needed
|
30
|
+
detach if repeated? # item did not exist individually yet, detach it within its parent and therefore make it individally editable
|
31
|
+
end
|
32
|
+
def detach
|
33
|
+
parent.detach_if_needed if parent.respond_to?(:detach_if_needed)
|
34
|
+
parent.detach_my_subnode_respect_repeated(index, xml_options)
|
35
|
+
self
|
36
|
+
end
|
37
|
+
def shift_by(diff)
|
38
|
+
set_index(index + diff)
|
39
|
+
end
|
40
|
+
def range
|
41
|
+
parent.find_my_subnode_range_respect_repeated(index,xml_options)
|
42
|
+
end
|
43
|
+
def invalid_reference?; false end
|
44
|
+
# destroys the object so it can not be used, this is necessarry to prevent
|
45
|
+
# accessing cells and rows which has been long time ago deleted and do not represent
|
46
|
+
# any physical object anymore
|
47
|
+
def invalidate_myself
|
48
|
+
raise_destroyed_cell_error = Proc.new {|*params| raise "Calling method of already destroyed Cell."}
|
49
|
+
(self.methods - Object.methods + [:nil?]).each do |method| # "undefine" all methods
|
50
|
+
self.singleton_class.send(:define_method, method, raise_destroyed_cell_error)
|
51
|
+
end
|
52
|
+
self.singleton_class.send(:define_method, :inspect, -> { "#<%s:0x%x destroyed cell>" % [self.class,object_id] }) # define descriptive inspect
|
53
|
+
self.singleton_class.send(:define_method, :invalid_reference?, -> { true }) # define invalid_reference? method
|
54
|
+
# self.instance_variables.each do |variable|
|
55
|
+
# instance_variable_set(variable,nil)
|
56
|
+
# end
|
57
|
+
end
|
58
|
+
def delete
|
59
|
+
parent.delete_subitem(index)
|
60
|
+
invalidate_myself
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# abstrac class. All successort MUST implement: prepare_subitem
|
65
|
+
# terminology
|
66
|
+
# item, subitem is object from @itemcache (quite often subclass of XMLTiedItem)
|
67
|
+
# node, subnode is LibXML::XML::Node object
|
68
|
+
|
69
|
+
module XMLTiedArray
|
70
|
+
attr_reader :itemcache
|
71
|
+
|
72
|
+
def find_my_subnode_range_respect_repeated(aindex, options)
|
73
|
+
index = 0
|
74
|
+
xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
75
|
+
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
76
|
+
if index+repeated >= aindex
|
77
|
+
return (index+1..index+repeated)
|
78
|
+
else
|
79
|
+
index = index+repeated
|
80
|
+
end
|
81
|
+
end
|
82
|
+
return (index+1..Float::INFINITY)
|
83
|
+
end
|
84
|
+
|
85
|
+
# vrátí xmlnode na souřadnici aindex
|
86
|
+
def find_my_subnode_respect_repeated(aindex, options)
|
87
|
+
find_subnode_respect_repeated(xmlnode,aindex, options)
|
88
|
+
end
|
89
|
+
# vrátí item na souřadnici aindex
|
90
|
+
def subitem(aindex)
|
91
|
+
aindex = aindex.to_i
|
92
|
+
if aindex.to_i<=0
|
93
|
+
nil
|
94
|
+
else
|
95
|
+
@itemcache[aindex] ||= prepare_subitem(aindex)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def subitems_array
|
100
|
+
(1..(find_first_unused_index_respect_repeated(subitem_xml_options)-1)).collect do |i|
|
101
|
+
subitem(i)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def find_subnode_respect_repeated(axmlnode, aindex, options)
|
106
|
+
result1, result2 = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
|
107
|
+
return result1
|
108
|
+
end
|
109
|
+
|
110
|
+
def find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
|
111
|
+
index = 0
|
112
|
+
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
113
|
+
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
114
|
+
oldindex = index
|
115
|
+
index = index+repeated
|
116
|
+
if index>= aindex
|
117
|
+
return node, oldindex..index
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return nil, index..Float::INFINITY
|
121
|
+
end
|
122
|
+
|
123
|
+
def prepare_repeated_subnode(times_repeated,options)
|
124
|
+
result = LibXML::XML::Node.new(options[:xml_items_node_name],nil, Tools.get_namespace('table'))
|
125
|
+
Tools.set_ns_attribute(result,'table',options[:xml_repeated_attribute],times_repeated, 1)
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
def clone_before_and_set_repeated_attribute(node,times_repeated,options)
|
130
|
+
newnode = node.copy(true)
|
131
|
+
Tools.set_ns_attribute(newnode,'table',options[:xml_repeated_attribute],times_repeated,1)
|
132
|
+
node.prev = newnode
|
133
|
+
end
|
134
|
+
|
135
|
+
# detaches subnode with aindex
|
136
|
+
def detach_my_subnode_respect_repeated(aindex, options)
|
137
|
+
axmlnode = xmlnode
|
138
|
+
node,index_range = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
|
139
|
+
if index_range.size > 1 # pokud potřebuje vůbec detachovat
|
140
|
+
if !node.nil? # detach subnode
|
141
|
+
[index_range.begin+1..aindex-1,aindex..aindex,aindex+1..index_range.end].reject {|range| range.size<1}.each do |range| # create new structure by cloning
|
142
|
+
clone_before_and_set_repeated_attribute(node,range.size,options)
|
143
|
+
end
|
144
|
+
node.remove! # remove the original node
|
145
|
+
else # add outbound xmlnode
|
146
|
+
[index_range.begin+1..aindex-1,aindex..aindex].reject {|range| range.size<1}.each do |range|
|
147
|
+
axmlnode << prepare_repeated_subnode(range.size, options)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
return find_subnode_respect_repeated(axmlnode, aindex, options)
|
152
|
+
end
|
153
|
+
|
154
|
+
def insert_my_subnode_before_respect_repeated(aindex, options)
|
155
|
+
axmlnode = xmlnode
|
156
|
+
|
157
|
+
node,index_range = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
|
158
|
+
|
159
|
+
if !node.nil? # found the node, now do the insert
|
160
|
+
[index_range.begin+1..aindex-1,aindex..index_range.end].reject {|range| range.size<1}.each do |range| # split original node by cloning
|
161
|
+
clone_before_and_set_repeated_attribute(node,range.size,options)
|
162
|
+
end
|
163
|
+
clone_before_and_set_repeated_attribute(node.prev,1,options) # insert new node
|
164
|
+
node.remove! # remove the original node
|
165
|
+
else # insert outbound xmlnode
|
166
|
+
[index+1..aindex-1,aindex..aindex].reject {|range| range.size<1}.each do |range|
|
167
|
+
axmlnode << XMLTiedArray.prepare_repeated_subnode(range.size, options)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
return find_subnode_respect_repeated(axmlnode, aindex, options)
|
171
|
+
end
|
172
|
+
|
173
|
+
def delete_my_subnode_respect_repeated(aindex,options)
|
174
|
+
detach_my_subnode_respect_repeated(aindex,options) #TODO: tohle neni uplne spravne, protoze to zanecha skupinu rozdelenou na dve casti
|
175
|
+
subitem(aindex).xmlnode.remove!
|
176
|
+
end
|
177
|
+
|
178
|
+
def find_first_unused_index_respect_repeated(options)
|
179
|
+
index = 0
|
180
|
+
xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
181
|
+
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
182
|
+
index = index+repeated
|
183
|
+
end
|
184
|
+
return index+1
|
185
|
+
end
|
186
|
+
|
187
|
+
def insert_subitem_before(aindex)
|
188
|
+
insert_subitem_before_with_options(aindex,subitem_xml_options)
|
189
|
+
end
|
190
|
+
def insert_subitem_before_with_options(aindex,options)
|
191
|
+
@itemcache.keys.sort.reverse.select{|i| i>=aindex }.each do |i|
|
192
|
+
@itemcache[i+1]=@itemcache.delete(i)
|
193
|
+
@itemcache[i+1].shift_by(1)
|
194
|
+
end
|
195
|
+
insert_my_subnode_before_respect_repeated(aindex,options) # nyní vlož node do xml
|
196
|
+
@itemcache[aindex] = subitem(aindex)
|
197
|
+
end
|
198
|
+
|
199
|
+
# clean up item from xml (handle possible detachments) and itemcache. leave the object invalidation on the object
|
200
|
+
# this should not be called from nowhere but XMLTiedItem.delete
|
201
|
+
def delete_subitem(aindex)
|
202
|
+
options = subitem_xml_options
|
203
|
+
delete_my_subnode_respect_repeated(aindex,options) # vymaž node z xml
|
204
|
+
@itemcache.delete(aindex)
|
205
|
+
@itemcache.keys.sort.select{|i| i>=aindex+1 }.each do |i|
|
206
|
+
@itemcache[i-1]=@itemcache.delete(i)
|
207
|
+
@itemcache[i-1].shift_by(-1)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def delete
|
212
|
+
@itemcache.each do |key,item|
|
213
|
+
item.delete # delete item - this destroys its subitems, xmlnode and invalidates it
|
214
|
+
@itemcache.delete(key) # delete the entry from the hash, normally this would mean this ceases to exist, if user does not have reference stored somewhere. Of he does, the object is invalidated anyways
|
215
|
+
end
|
216
|
+
super # this for example for Row objects calls XMLTiedItem.delete
|
217
|
+
end
|
218
|
+
|
219
|
+
def find_nonempty_subnode_indexes(axmlnode, options)
|
220
|
+
index = 0
|
221
|
+
result = []
|
222
|
+
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
223
|
+
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
224
|
+
index = index + repeated
|
225
|
+
if !(node.content.nil? or node.content.empty? or node.content =='') and (repeated==1)
|
226
|
+
result << index
|
227
|
+
end
|
228
|
+
end
|
229
|
+
return result
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
data/lib/rspreadsheet.rb
CHANGED
data/reinstall2.sh
ADDED
data/rspreadsheet.gemspec
CHANGED
@@ -22,19 +22,18 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_runtime_dependency 'libxml-ruby', '~>2.7' # parsing XML files
|
23
23
|
spec.add_runtime_dependency 'rubyzip', '~>1.1' # opening zip files
|
24
24
|
spec.add_runtime_dependency 'andand', '~>1.3'
|
25
|
-
|
26
|
-
|
25
|
+
|
27
26
|
# development dependencies
|
28
27
|
spec.add_development_dependency "bundler", "~> 1.5"
|
29
28
|
spec.add_development_dependency "rake", '~>0.9'
|
30
29
|
# testig - see http://bit.ly/1n5yM51
|
31
|
-
spec.add_development_dependency "rspec", '~>2'
|
32
|
-
spec.add_development_dependency 'pry-nav', '~>0'
|
33
|
-
|
30
|
+
spec.add_development_dependency "rspec", '~>2' # testing
|
31
|
+
spec.add_development_dependency 'pry-nav', '~>0' # enables pry 'next', 'step' commands
|
32
|
+
|
34
33
|
# optional and testing
|
35
34
|
spec.add_development_dependency "coveralls", '~>0.7'
|
36
35
|
spec.add_development_dependency "guard", '~>2.6'
|
37
36
|
spec.add_development_dependency "guard-rspec", '~>2.6'
|
38
|
-
# spec.add_development_dependency 'equivalent-xml'
|
39
|
-
|
37
|
+
# spec.add_development_dependency 'equivalent-xml' # implementing xml diff
|
38
|
+
|
40
39
|
end
|