Cache output of Element#available_namespaces
This cache is flushed whenever Element#register_namespace is called. When this cache is flushed it's also recursively flushed for all child elements. This makes calls to Element#register_namespace a bit more expensive but in turn calls to Element#available_namespaces will be a lot faster.
This commit is contained in:
1 parent
fa838154fc
commit
b42f9aaf32
2 files changed
+83
-10
No files matched your search
+39
-10
@@ -299,14 +299,17 @@ module Oga
|
||||
#
|
||||
# @param [String] name
|
||||
# @param [String] uri
|
||||
# @param [TrueClass|FalseClass] flush
|
||||
# @see [Oga::XML::Namespace#initialize]
|
||||
#
|
||||
def register_namespace(name, uri)
|
||||
def register_namespace(name, uri, flush = true)
|
||||
if namespaces[name]
|
||||
raise ArgumentError, "The namespace #{name.inspect} already exists"
|
||||
end
|
||||
|
||||
namespaces[name] = Namespace.new(:name => name, :uri => uri)
|
||||
|
||||
flush_namespaces_cache if flush
|
||||
end
|
||||
|
||||
##
|
||||
@@ -316,20 +319,25 @@ module Oga
|
||||
# @return [Hash]
|
||||
#
|
||||
def available_namespaces
|
||||
return {} if html? # HTML(5) completely ignores namespaces
|
||||
# HTML(5) completely ignores namespaces
|
||||
if html?
|
||||
return @available_namespaces ||= {}
|
||||
elsif !@available_namespaces
|
||||
merged = namespaces.dup
|
||||
node = parent
|
||||
|
||||
merged = namespaces.dup
|
||||
node = parent
|
||||
while node && node.respond_to?(:namespaces)
|
||||
node.namespaces.each do |prefix, ns|
|
||||
merged[prefix] = ns unless merged[prefix]
|
||||
end
|
||||
|
||||
while node && node.respond_to?(:namespaces)
|
||||
node.namespaces.each do |prefix, ns|
|
||||
merged[prefix] = ns unless merged[prefix]
|
||||
node = node.parent
|
||||
end
|
||||
|
||||
node = node.parent
|
||||
@available_namespaces = merged
|
||||
end
|
||||
|
||||
return merged
|
||||
return @available_namespaces
|
||||
end
|
||||
|
||||
##
|
||||
@@ -349,19 +357,40 @@ module Oga
|
||||
return self_closing
|
||||
end
|
||||
|
||||
##
|
||||
# Flushes the namespaces cache of the current element and all its child
|
||||
# elements.
|
||||
#
|
||||
def flush_namespaces_cache
|
||||
@available_namespaces = nil
|
||||
@namespace = nil
|
||||
|
||||
children.each do |child|
|
||||
child.flush_namespaces_cache if child.is_a?(Element)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
##
|
||||
# Registers namespaces based on any "xmlns" attributes.
|
||||
#
|
||||
def register_namespaces_from_attributes
|
||||
flush = false
|
||||
|
||||
attributes.each do |attr|
|
||||
# We're using `namespace_name` opposed to `namespace.name` as "xmlns"
|
||||
# is not a registered namespace.
|
||||
if attr.name == XMLNS_PREFIX or attr.namespace_name == XMLNS_PREFIX
|
||||
register_namespace(attr.name, attr.value)
|
||||
flush = true
|
||||
|
||||
# Ensures we only flush the cache once instead of flushing it on
|
||||
# every register_namespace call.
|
||||
register_namespace(attr.name, attr.value, false)
|
||||
end
|
||||
end
|
||||
|
||||
flush_namespaces_cache if flush
|
||||
end
|
||||
|
||||
##
|
||||
|
||||
Reference in new issue
Block a user