Skip to content

🐛 Properly handle XPathParser#document, Child#document # => nil #261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions lib/rexml/child.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,12 @@ def previous_sibling=(other)
# Returns:: the document this child belongs to, or nil if this child
# belongs to no document
def document
return parent.document unless parent.nil?
nil
parent&.document
end

# This doesn't yet handle encodings
def bytes
document.encoding
document&.encoding

to_s
end
Expand Down
29 changes: 14 additions & 15 deletions lib/rexml/element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,7 @@ def root
# Related: #root, #root_node.
#
def document
rt = root
rt.parent if rt
root&.parent
end

# :call-seq:
Expand Down Expand Up @@ -2325,11 +2324,11 @@ def get_attribute( name )
return attr
end
end
element_document = @element.document
if element_document and element_document.doctype
doctype = @element.document&.doctype
if doctype
expn = @element.expanded_name
expn = element_document.doctype.name if expn.size == 0
attr_val = element_document.doctype.attribute_of(expn, name)
expn = doctype.name if expn.size == 0
attr_val = doctype.attribute_of(expn, name)
return Attribute.new( name, attr_val ) if attr_val
end
return nil
Expand Down Expand Up @@ -2371,8 +2370,8 @@ def []=( name, value )
end

unless value.kind_of? Attribute
if @element.document and @element.document.doctype
value = Text::normalize( value, @element.document.doctype )
if @element.document and (doctype = @element.document&.doctype)
value = Text::normalize( value, doctype )
else
value = Text::normalize( value, nil )
end
Expand All @@ -2390,7 +2389,7 @@ def []=( name, value )
else
store value.name, value
end
return @element
@element
end

# :call-seq:
Expand All @@ -2409,10 +2408,10 @@ def prefixes
each_attribute do |attribute|
ns << attribute.name if attribute.prefix == 'xmlns'
end
if @element.document and @element.document.doctype
if @element.document and (doctype = @element.document&.doctype)
expn = @element.expanded_name
expn = @element.document.doctype.name if expn.size == 0
@element.document.doctype.attributes_of(expn).each {
expn = doctype.name if expn.size == 0
doctype.attributes_of(expn).each {
|attribute|
ns << attribute.name if attribute.prefix == 'xmlns'
}
Expand All @@ -2434,10 +2433,10 @@ def namespaces
each_attribute do |attribute|
namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
end
if @element.document and @element.document.doctype
if @element.document and (doctype = @element.document&.doctype)
expn = @element.expanded_name
expn = @element.document.doctype.name if expn.size == 0
@element.document.doctype.attributes_of(expn).each {
expn = doctype.name if expn.size == 0
doctype.attributes_of(expn).each {
|attribute|
namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
}
Expand Down
3 changes: 1 addition & 2 deletions lib/rexml/text.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,7 @@ def <=>( other )

def doctype
if @parent
doc = @parent.document
doc.doctype if doc
@parent.document&.doctype
end
end

Expand Down
14 changes: 3 additions & 11 deletions lib/rexml/xpath.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@ class XPath
def XPath::first(element, path=nil, namespaces=nil, variables={}, options={})
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 = XPathParser.new(**options)
parser.namespaces = namespaces
parser.variables = variables
path = "*" unless path
parser.parse(path, element).flatten[0]
match(element, path, namespaces, variables, options).flatten[0]
end

# Iterates over nodes that match the given path, calling the supplied
Expand All @@ -59,11 +55,7 @@ def XPath::first(element, path=nil, namespaces=nil, variables={}, options={})
def XPath::each(element, path=nil, namespaces=nil, variables={}, options={}, &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 = XPathParser.new(**options)
parser.namespaces = namespaces
parser.variables = variables
path = "*" unless path
parser.parse(path, element).each( &block )
match(element, path, namespaces, variables, options).each( &block )
end

# Returns an array of nodes matching a given XPath.
Expand All @@ -72,7 +64,7 @@ def XPath::match(element, path=nil, namespaces=nil, variables={}, options={})
parser.namespaces = namespaces
parser.variables = variables
path = "*" unless path
parser.parse(path,element)
parser.parse(path,element) || []
end
end
end
2 changes: 1 addition & 1 deletion lib/rexml/xpath_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def parse path, node
node = node.first
end

node.document.__send__(:enable_cache) do
node.document&.__send__(:enable_cache) do
match( path_stack, node )
end
end
Expand Down