summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorkou <kou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-22 08:09:04 +0000
committerkou <kou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-04-22 08:09:04 +0000
commit4d15e619eb1838daafd1510e86c1c8076fb9b227 (patch)
tree52009b7046146ad093bcd91db9b7b22f7e38bb0b /lib
parentb252d8ada355ab729a545274e107d3f082f1fde6 (diff)
rexml: Fix XPath bug of /#{ELEMENT_NAME}
It doesn't mean that all elements which name "ELEMENT_NAME" with any namespace URI including null namespace URI. It means that all elements which name "ELEMENT_NAME" with null namespace URI. https://www.w3.org/TR/1999/REC-xpath-19991116/#NT-NodeTest > if the QName does not have a prefix, then the namespace URI is null > (this is the same way attribute names are expanded). We need to use "*[local-name()='#{ELEMENT_NAME}']" for all elements which name "ELEMENT_NAME" with any namespace URI including null namespace URI in XPath 1.0. But it's inconvenient. So this change includes "*:#{LOCAL_NAME}" syntax support that is introduced since XPath 2.0. * lib/rexml/parsers/xpathparser.rb: Support "*:#{LOCAL_NAME}" syntax that is introduced since XPath 2.0. * lib/rexml/xpath_parser.rb: * Fix namespace URI processing for "#{ELEMENT_NAME}". Now, "#{ELEMENT_NAME}" doesn't accept elements with null namespace URI. * Add "*:#{LOCAL_NAME}" support. * test/rexml/test_contrib.rb, test/rexml/test_core.rb, test/rexml/xpath/test_base.rb: Follow this change. * test/rexml/test_jaxen.rb: Fix namespace processing. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/rexml/parsers/xpathparser.rb15
-rw-r--r--lib/rexml/xpath_parser.rb18
2 files changed, 23 insertions, 10 deletions
diff --git a/lib/rexml/parsers/xpathparser.rb b/lib/rexml/parsers/xpathparser.rb
index 304dc51698..ac3c4d4e67 100644
--- a/lib/rexml/parsers/xpathparser.rb
+++ b/lib/rexml/parsers/xpathparser.rb
@@ -271,10 +271,12 @@ module REXML
# String, if a name match
#NodeTest
# | ('*' | NCNAME ':' '*' | QNAME) NameTest
- # | NODE_TYPE '(' ')' NodeType
+ # | '*' ':' NCNAME NameTest since XPath 2.0
+ # | NODE_TYPE '(' ')' NodeType
# | PI '(' LITERAL ')' PI
# | '[' expr ']' Predicate
- NCNAMETEST= /^(#{NCNAME_STR}):\*/u
+ PREFIX_WILDCARD = /^\*:(#{NCNAME_STR})/u
+ LOCAL_NAME_WILDCARD = /^(#{NCNAME_STR}):\*/u
QNAME = Namespace::NAMESPLIT
NODE_TYPE = /^(comment|text|node)\(\s*\)/m
PI = /^processing-instruction\(/
@@ -282,6 +284,13 @@ module REXML
original_path = path
path = path.lstrip
case path
+ when PREFIX_WILDCARD
+ prefix = nil
+ name = $1
+ path = $'
+ parsed << :qname
+ parsed << prefix
+ parsed << name
when /^\*/
path = $'
parsed << :any
@@ -301,7 +310,7 @@ module REXML
end
parsed << :processing_instruction
parsed << (literal || '')
- when NCNAMETEST
+ when LOCAL_NAME_WILDCARD
prefix = $1
path = $'
parsed << :namespace
diff --git a/lib/rexml/xpath_parser.rb b/lib/rexml/xpath_parser.rb
index a94ad91ea1..d217ae78e8 100644
--- a/lib/rexml/xpath_parser.rb
+++ b/lib/rexml/xpath_parser.rb
@@ -169,16 +169,20 @@ module REXML
prefix = path_stack.shift
name = path_stack.shift
# enter(:qname, path_stack, prefix, name, nodeset)
- nodeset.delete_if do |node|
- # FIXME: This DOUBLES the time XPath searches take
- ns = get_namespace( node, prefix )
+ nodeset.select! do |node|
if node.node_type == :element
- if node.name == name
+ if prefix.nil?
+ node.name == name
+ elsif prefix.empty?
+ node.name == name and node.namespace == ""
+ else
+ node.name == name and
+ # FIXME: This DOUBLES the time XPath searches take
+ node.namespace == get_namespace(node, prefix)
end
+ else
+ false
end
- !(node.node_type == :element and
- node.name == name and
- node.namespace == ns )
end
# leave(:qname, path_stack, nodeset)
node_types = ELEMENTS