-
Notifications
You must be signed in to change notification settings - Fork 2
/
caching-xpath.rb
55 lines (47 loc) · 1.79 KB
/
caching-xpath.rb
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
# A caching XPath implementation, to gain us a bit of performance...
require 'rexml/document'
class CachingXPathParser < REXML::XPathParser
def initialize
@cache = {}
super
end
def parse path, nodeset
path_stack = @cache[path]
if path_stack.nil? or (not @namespaces.nil?) or (@variables != {})
path_stack = @parser.parse( path )
@cache[path] = path_stack
end
match( path_stack.dclone, nodeset )
end
end
class CachingXPath
def initialize
@parser = CachingXPathParser.new
end
def first element, path=nil, namespaces=nil, variables={}
raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
@parser.namespaces = namespaces
@parser.variables = variables
path = "*" unless path
element = [element] unless element.kind_of? Array
@parser.parse(path, element).flatten[0]
end
def each element, path=nil, namespaces=nil, variables={}, &block
raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
@parser.namespaces = namespaces
@parser.variables = variables
path = "*" unless path
element = [element] unless element.kind_of? Array
@parser.parse(path, element).each( &block )
end
# Returns an array of nodes matching a given XPath.
def match element, path=nil, namespaces=nil, variables={}
@parser.namespaces = namespaces
@parser.variables = variables
path = "*" unless path
element = [element] unless element.kind_of? Array
@parser.parse(path,element)
end
end