1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
#!/usr/bin/ruby
require 'xml'
require 'ftools'
#class Array; def sum; inject( 0 ) { |sum,x| sum+x }; end; end
def calc(node)
res = Float(node.child.content) rescue 0 if (node.child and node.child.text?())
return res if (res)
node.each_attr do |attr|
res = Float(attr.child.content) rescue 0
return res if (res)
end
return 0
end
def siblings(node)
res = 0
# i=0;
# node.children.each { |cur_node|
# break if (i+=1)>3
# }
# cond = if (i>3); 1 else; nil end
cond = (node.children.length>3)?1:nil;
node.children.each { |cur_node|
if cur_node.element?
if cond
# res += calc(cur_node)
val = Float(cur_node.child.content) rescue 0 if (cur_node.child and cur_node.child.text?())
if (val)
res += val
else
cur_node.each_attr do |attr|
val = Float(attr.child.content) rescue 0
if (val)
res += val
break
end
end
end
end
res += siblings(cur_node)
end
}
return res
end
def parse(xml, walk)
# Does not close a file, complines if many iterations are involved
# parser = XML::Parser.file(xml)
# doc = parser.parse
f = File.new(xml);
parser = XML::Parser.io(f)
doc = parser.parse
# print doc
if (walk)
# This is slowest 330 ms
# sum = siblings(doc.root)
sum = 0
# doc.find("//*[(@* or text()) and (count(../child::*)>3)]").each do |node|
# nodes = doc.find("//*[(number(@*) or number(text())) and (count(../child::*)>3)]")
# nodes.each do |node|
doc.find("//*[count(child::*)>3]/*[number(@*) or number(text())]").each do |node|
# 190 ms
# sum += calc(node)
#Fastest approach ~ 177ms
res = Float(node.child.content) rescue 0 if (node.child and node.child.text?())
if (res)
sum += res
else
node.each_attr do |attr|
res = Float(attr.child.content) rescue 0
if (res)
sum += res
break
end
end
end
end
# nodes = nil
=begin
sum = doc.find("//*[(number(@*) or number(text())) and (count(../child::*)>3)]").map { |node|
res = Float(node.child.content) rescue nil if (node.child and node.child.text?())
next res if ((res)&&(res!=0))
node.each_attr do |attr|
res = Float(attr.child.content) rescue nil
break res if ((res)&&(res!=0))
end
}.sum
=end
=begin
sum = doc.find("//*[(number(@*) or number(text())) and (count(../child::*)>3)]").inject(0) { |sum, node|
res = Float(node.child.content) rescue nil if (node.child and node.child.text?())
next sum+res if ((res)&&(res!=0))
node.each_attr do |attr|
res = Float(attr.child.content) rescue nil
break res if ((res)&&(res!=0))
end + sum
}
=end
# print "Sum: #{sum}\n"
end
f.close
end
walk_tree = ENV['walk_tree']
if ($*.length > 0)
iterations = $*[0].to_i
else
iterations = 0
end
if ($*.length > 1)
filename = lambda { |i| $*[1] }
else
filename = lambda { |i| "../xml.tmp/#{i}.xml" }
end
parse(filename.call(0), walk_tree)
iterations.times { |i|
parse(filename.call(i+1), walk_tree)
}
|