Reworked handling of relative vs absolute XPaths.
This commit is contained in:
parent
a733869f53
commit
2298ef618b
|
@ -16,31 +16,27 @@ preclow
|
||||||
|
|
||||||
rule
|
rule
|
||||||
xpath
|
xpath
|
||||||
: expressions { s(:xpath, *val[0]) }
|
: T_SLASH expression { s(:absolute, val[1]) }
|
||||||
| /* none */ { s(:xpath) }
|
| expression { val[0] }
|
||||||
;
|
| /* none */ { nil }
|
||||||
|
|
||||||
expressions
|
|
||||||
: expressions expression { val[0] << val[1] }
|
|
||||||
| expression { val }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
expression
|
expression
|
||||||
: path
|
: node_tests
|
||||||
| node_test
|
|
||||||
| operator
|
| operator
|
||||||
| axis
|
| axis
|
||||||
| string
|
| string
|
||||||
| number
|
| number
|
||||||
;
|
;
|
||||||
|
|
||||||
path
|
node_tests
|
||||||
: T_SLASH node_test { s(:path, val[1]) }
|
: node_test { val[0] }
|
||||||
|
| node_test T_SLASH node_tests { val[0].append(val[2]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
node_test
|
node_test
|
||||||
: node_name { s(:node_test, val[0]) }
|
: node_name { s(:test, val[0]) }
|
||||||
| node_name predicate { s(:node_test, val[0], *val[1]) }
|
| node_name predicate { s(:test, val[0], val[1]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
node_name
|
node_name
|
||||||
|
@ -52,7 +48,7 @@ rule
|
||||||
;
|
;
|
||||||
|
|
||||||
predicate
|
predicate
|
||||||
: T_LBRACK expressions T_RBRACK { val[1] }
|
: T_LBRACK xpath T_RBRACK { s(:predicate, val[1]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
operator
|
operator
|
||||||
|
@ -61,7 +57,7 @@ rule
|
||||||
;
|
;
|
||||||
|
|
||||||
axis
|
axis
|
||||||
: T_AXIS T_IDENT { s(:axis, val[0], val[1]) }
|
: T_AXIS node_name { s(:axis, val[0], val[1]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
string
|
string
|
||||||
|
|
|
@ -4,104 +4,92 @@ describe Oga::XPath::Parser do
|
||||||
context 'full axes' do
|
context 'full axes' do
|
||||||
example 'parse the ancestor axis' do
|
example 'parse the ancestor axis' do
|
||||||
parse_xpath('/ancestor::A').should == s(
|
parse_xpath('/ancestor::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'ancestor', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'ancestor', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the ancestor-or-self axis' do
|
example 'parse the ancestor-or-self axis' do
|
||||||
parse_xpath('/ancestor-or-self::A').should == s(
|
parse_xpath('/ancestor-or-self::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(
|
s(:test, s(:axis, 'ancestor-or-self', s(:name, nil, 'A')))
|
||||||
:path,
|
|
||||||
s(:node_test, s(:axis, 'ancestor-or-self', s(:name, nil, 'A')))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the attribute axis' do
|
example 'parse the attribute axis' do
|
||||||
parse_xpath('/attribute::A').should == s(
|
parse_xpath('/attribute::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'attribute', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'attribute', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the child axis' do
|
example 'parse the child axis' do
|
||||||
parse_xpath('/child::A').should == s(
|
parse_xpath('/child::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'child', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'child', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the descendant axis' do
|
example 'parse the descendant axis' do
|
||||||
parse_xpath('/descendant::A').should == s(
|
parse_xpath('/descendant::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'descendant', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'descendant', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the descendant-or-self axis' do
|
example 'parse the descendant-or-self axis' do
|
||||||
parse_xpath('/descendant-or-self::A').should == s(
|
parse_xpath('/descendant-or-self::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(
|
s(:test, s(:axis, 'descendant-or-self', s(:name, nil, 'A')))
|
||||||
:path,
|
|
||||||
s(:node_test, s(:axis, 'descendant-or-self', s(:name, nil, 'A')))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the following axis' do
|
example 'parse the following axis' do
|
||||||
parse_xpath('/following::A').should == s(
|
parse_xpath('/following::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'following', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'following', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the following-sibling axis' do
|
example 'parse the following-sibling axis' do
|
||||||
parse_xpath('/following-sibling::A').should == s(
|
parse_xpath('/following-sibling::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(
|
s(:test, s(:axis, 'following-sibling', s(:name, nil, 'A')))
|
||||||
:path,
|
|
||||||
s(:node_test, s(:axis, 'following-sibling', s(:name, nil, 'A')))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the namespace axis' do
|
example 'parse the namespace axis' do
|
||||||
parse_xpath('/namespace::A').should == s(
|
parse_xpath('/namespace::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'namespace', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'namespace', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the parent axis' do
|
example 'parse the parent axis' do
|
||||||
parse_xpath('/parent::A').should == s(
|
parse_xpath('/parent::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'parent', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'parent', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the preceding axis' do
|
example 'parse the preceding axis' do
|
||||||
parse_xpath('/preceding::A').should == s(
|
parse_xpath('/preceding::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'preceding', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'preceding', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the preceding-sibling axis' do
|
example 'parse the preceding-sibling axis' do
|
||||||
parse_xpath('/preceding-sibling::A').should == s(
|
parse_xpath('/preceding-sibling::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(
|
s(:test, s(:axis, 'preceding-sibling', s(:name, nil, 'A')))
|
||||||
:path,
|
|
||||||
s(:node_test, s(:axis, 'preceding-sibling', s(:name, nil, 'A')))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the self axis' do
|
example 'parse the self axis' do
|
||||||
parse_xpath('/self::A').should == s(
|
parse_xpath('/self::A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'self', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'self', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -109,32 +97,29 @@ describe Oga::XPath::Parser do
|
||||||
context 'short axes' do
|
context 'short axes' do
|
||||||
example 'parse the @attribute axis' do
|
example 'parse the @attribute axis' do
|
||||||
parse_xpath('/@A').should == s(
|
parse_xpath('/@A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'attribute', s(:name, nil, 'A'))))
|
s(:test, s(:axis, 'attribute', s(:name, nil, 'A')))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the // axis' do
|
example 'parse the // axis' do
|
||||||
parse_xpath('//A').should == s(
|
parse_xpath('//A').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(
|
s(:test, s(:axis, 'descendant-or-self', s(:name, nil, 'A')))
|
||||||
:path,
|
|
||||||
s(:node_test, s(:axis, 'descendant-or-self', s(:name, nil, 'A')))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the .. axis' do
|
example 'parse the .. axis' do
|
||||||
parse_xpath('/..').should == s(
|
parse_xpath('/..').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'parent')))
|
s(:test, s(:axis, 'parent'))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the . axis' do
|
example 'parse the . axis' do
|
||||||
parse_xpath('/.').should == s(
|
parse_xpath('/.').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:axis, 'self')))
|
s(:test, s(:axis, 'self'))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,21 +3,17 @@ require 'spec_helper'
|
||||||
describe Oga::XPath::Parser do
|
describe Oga::XPath::Parser do
|
||||||
context 'paths' do
|
context 'paths' do
|
||||||
example 'parse an absolute path' do
|
example 'parse an absolute path' do
|
||||||
parse_xpath('/foo').should == s(
|
parse_xpath('/A').should == s(:absolute, s(:test, s(:name, nil, 'A')))
|
||||||
:xpath,
|
|
||||||
s(:path, s(:node_test, s(:name, nil, 'foo')))
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse a relative path' do
|
example 'parse a relative path' do
|
||||||
parse_xpath('foo').should == s(:xpath, s(:node_test, s(:name, nil, 'foo')))
|
parse_xpath('A').should == s(:test, s(:name, nil, 'A'))
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse an expression using two paths' do
|
example 'parse an expression using two paths' do
|
||||||
parse_xpath('/foo/bar').should == s(
|
parse_xpath('/A/B').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(:path, s(:node_test, s(:name, nil, 'foo'))),
|
s(:test, s(:name, nil, 'A'), s(:test, s(:name, nil, 'B')))
|
||||||
s(:path, s(:node_test, s(:name, nil, 'bar')))
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,12 +4,12 @@ describe Oga::XPath::Parser do
|
||||||
context 'predicates' do
|
context 'predicates' do
|
||||||
example 'parse a single predicate' do
|
example 'parse a single predicate' do
|
||||||
parse_xpath('/foo[@class="bar"]').should == s(
|
parse_xpath('/foo[@class="bar"]').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(
|
s(
|
||||||
:path,
|
:test,
|
||||||
s(
|
|
||||||
:node_test,
|
|
||||||
s(:name, nil, 'foo'),
|
s(:name, nil, 'foo'),
|
||||||
|
s(
|
||||||
|
:predicate,
|
||||||
s(
|
s(
|
||||||
:eq,
|
:eq,
|
||||||
s(:axis, 'attribute', s(:name, nil, 'class')),
|
s(:axis, 'attribute', s(:name, nil, 'class')),
|
||||||
|
@ -22,12 +22,12 @@ describe Oga::XPath::Parser do
|
||||||
|
|
||||||
example 'parse a predicate using the or operator' do
|
example 'parse a predicate using the or operator' do
|
||||||
parse_xpath('/foo[@class="bar" or @class="baz"]').should == s(
|
parse_xpath('/foo[@class="bar" or @class="baz"]').should == s(
|
||||||
:xpath,
|
:absolute,
|
||||||
s(
|
s(
|
||||||
:path,
|
:test,
|
||||||
s(
|
|
||||||
:node_test,
|
|
||||||
s(:name, nil, 'foo'),
|
s(:name, nil, 'foo'),
|
||||||
|
s(
|
||||||
|
:predicate,
|
||||||
s(
|
s(
|
||||||
:or,
|
:or,
|
||||||
s(
|
s(
|
||||||
|
|
Loading…
Reference in New Issue