diff --git a/lib/rexml/parsers/xpathparser.rb b/lib/rexml/parsers/xpathparser.rb index 7145d547..22f3c098 100644 --- a/lib/rexml/parsers/xpathparser.rb +++ b/lib/rexml/parsers/xpathparser.rb @@ -587,14 +587,21 @@ def PathExpr path, parsed path = path.lstrip n = [] rest = FilterExpr( path, n ) - if rest != path - if rest and rest[0] == ?/ + if rest == path + rest = LocationPath(rest, n) + else + if /\A\s*\//.match?(rest) + rest = rest.lstrip + if rest.start_with?('//') + n << :descendant_or_self + n << :node + rest = rest[2..-1] + else # starts with '/' + rest = rest[1..-1] + end rest = RelativeLocationPath(rest, n) - parsed.concat(n) - return rest end end - rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w*]/ parsed.concat(n) rest end diff --git a/test/parser/test_xpath.rb b/test/parser/test_xpath.rb index c62c1391..2484ed29 100644 --- a/test/parser/test_xpath.rb +++ b/test/parser/test_xpath.rb @@ -129,5 +129,18 @@ def test_spaces_between_tokens parser.parse('//processing-instruction( "a" )'), ) end + + def test_mult_asterisk_without_surrounding_spaces + parser = REXML::Parsers::XPathParser.new + assert_equal(parser.parse("1 * 2 * 3"), parser.parse("1*2*3")) + assert_equal(parser.parse("a[( ( 1 + 2 ) * 3 + 4 * ( 5 + 6 ) ) * 7 < 8]"), parser.parse("a[((1+2)*3+4*(5+6))*7<8]")) + # number(a/b) * 2 + assert_equal(parser.parse("(a/b) * 2"), parser.parse("(a/b)*2")) + assert_equal(parser.parse("a/b * 2"), parser.parse("a/b*2")) + # number(a/b/*) * 2 + assert_equal(parser.parse("a/b/* * 2"), parser.parse("a/b/**2")) + # number(*) * number(*/*) * number(*) + assert_equal(parser.parse("* * */* * *"), parser.parse("***/***")) + end end end diff --git a/test/xpath/test_base.rb b/test/xpath/test_base.rb index c7049d67..f6d01d85 100644 --- a/test/xpath/test_base.rb +++ b/test/xpath/test_base.rb @@ -616,6 +616,33 @@ def test_nested_predicates assert_equal without_parentheses, with_parentheses end + def test_parenthesized_xpath + doc = Document.new <<-EOF +