rind 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +6 -2
- data/lib/rind/manipulate.rb +5 -8
- data/lib/rind/xpath.rb +21 -15
- data/test/manipulate_test.rb +8 -7
- data/test/xml_test.rb +2 -2
- data/test/xpath_test.rb +70 -14
- metadata +7 -6
data/CHANGELOG.rdoc
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
== 0.1.4 - 2010.06.26
|
2
|
+
* Xpath searches with attribute values containing a <tt>/</tt>, like <tt>style[@type="text/css"]</tt>, broke the query parser.
|
3
|
+
* The Manipulate::insert_after and Manipulate::insert_before functions and Xpath positions were not returning the correct nodes when other available nodes matched <tt>==</tt>.
|
4
|
+
|
1
5
|
== 0.1.3 - 2010.06.20
|
2
6
|
* The Xpath function 's' will return an empty Rind::Node rather than +nil+.
|
3
7
|
* Processing instructions were not being treated as nodes.
|
4
8
|
* DocType nodes were lacking proper equality checks.
|
5
|
-
* The
|
6
|
-
* Adding
|
9
|
+
* The Traverse::next, Traverse::next_sibling, Traverse::prev and Traverse::prev_sibling functions were not returning the correct nodes when other available nodes matched <tt>==</tt>.
|
10
|
+
* Adding exact_index function to Rind::Nodes. (used in previous bug fix)
|
7
11
|
|
8
12
|
== 0.1.2 - 2010.06.17
|
9
13
|
* When parsing HTML, script and style tags will not break because of a "<" in their content.
|
data/lib/rind/manipulate.rb
CHANGED
@@ -1,27 +1,24 @@
|
|
1
1
|
# Note: These functions are not available for the root node in a tree.
|
2
2
|
module Manipulate
|
3
|
-
# Calls
|
4
|
-
# to add nodes after <tt>self</tt>.
|
3
|
+
# Calls Rind::Children::insert to add nodes after <tt>self</tt>.
|
5
4
|
# === Example
|
6
5
|
# nodes = ['a', 'b', 'c']
|
7
6
|
# nodes[0].insert_after('d', 'e') => ['a', 'd', 'e', 'b', 'c']
|
8
7
|
def insert_after(*nodes)
|
9
8
|
children = self.parent.children
|
10
|
-
children.insert(children.
|
9
|
+
children.insert(children.exact_index(self)+1, *nodes)
|
11
10
|
end
|
12
11
|
|
13
|
-
# Calls
|
14
|
-
# to add nodes before <tt>self</tt>.
|
12
|
+
# Calls Rind::Children::insert to add nodes before <tt>self</tt>.
|
15
13
|
# === Example
|
16
14
|
# nodes = ['a', 'b', 'c']
|
17
15
|
# nodes[2].insert_after('d', 'e') => ['a', 'b', 'd', 'e', 'c']
|
18
16
|
def insert_before(*nodes)
|
19
17
|
children = self.parent.children
|
20
|
-
children.insert(children.
|
18
|
+
children.insert(children.exact_index(self), *nodes)
|
21
19
|
end
|
22
20
|
|
23
|
-
# Calls
|
24
|
-
# on <tt>self</tt>.
|
21
|
+
# Calls Rind::Children::delete on <tt>self</tt>.
|
25
22
|
# === Example
|
26
23
|
# nodes = ['a', 'b', 'c']
|
27
24
|
# nodes[1].delete => 'b'
|
data/lib/rind/xpath.rb
CHANGED
@@ -4,38 +4,42 @@
|
|
4
4
|
module Xpath
|
5
5
|
# Xpath search of a node that returns a list of matching nodes.
|
6
6
|
def s(path)
|
7
|
-
node = self
|
7
|
+
node = self
|
8
8
|
|
9
9
|
# absolute paths to the top
|
10
10
|
if '/' == path[0,1]
|
11
11
|
while not node.parent.nil?
|
12
12
|
node = node.parent
|
13
13
|
end
|
14
|
-
if
|
15
|
-
path[0] = ''
|
16
|
-
else
|
14
|
+
if '/' != path[1,1]
|
17
15
|
path[0] = 'self::'
|
18
16
|
end
|
19
17
|
end
|
20
18
|
|
21
19
|
# node check
|
22
20
|
nodes = [node]
|
23
|
-
path.
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
path.scan(%r{(?:^\/?|\/)
|
22
|
+
(?:(.*?)::)? # axis
|
23
|
+
([^\/\[]+)? # node test
|
24
|
+
((?:\[.+?\])*) # predicates
|
25
|
+
}x) do |axis, node_test, predicates|
|
26
|
+
case node_test
|
27
|
+
when nil
|
28
|
+
axis = 'descendant-or-self'
|
29
|
+
node_test = 'node()'
|
27
30
|
when '.'
|
28
|
-
|
31
|
+
axis = 'self'
|
32
|
+
node_test = 'node()'
|
29
33
|
when '..'
|
30
|
-
|
34
|
+
axis = 'parent'
|
35
|
+
node_test = 'node()'
|
31
36
|
end
|
32
37
|
|
33
|
-
step.gsub!(/^@/, 'attribute::')
|
34
|
-
|
35
|
-
step =~ /^(?:(.*?)::)?(.+?)(\[.*?)?$/
|
36
|
-
axis, node_test, predicates = $1, $2, $3
|
37
38
|
axis = 'child' if axis.nil?
|
38
39
|
|
40
|
+
node_test.gsub!(/^@/, 'attribute::')
|
41
|
+
predicates.gsub!(/^@/, 'attribute::')
|
42
|
+
|
39
43
|
# find matching nodes
|
40
44
|
nodes = nodes.collect{|node| node.find_matching_nodes(axis, node_test)}.flatten.compact
|
41
45
|
|
@@ -51,7 +55,9 @@ module Xpath
|
|
51
55
|
# last()
|
52
56
|
predicate.gsub!(/last\(\)/, nodes.length.to_s)
|
53
57
|
|
54
|
-
nodes = nodes.find_all
|
58
|
+
nodes = nodes.find_all do |node|
|
59
|
+
node.validate_predicate(predicate.clone, Rind::Nodes[*nodes].exact_index(node)+1)
|
60
|
+
end
|
55
61
|
break if nodes.empty?
|
56
62
|
end
|
57
63
|
end
|
data/test/manipulate_test.rb
CHANGED
@@ -3,21 +3,22 @@ require 'rind'
|
|
3
3
|
|
4
4
|
class ManipulateTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@
|
6
|
+
@a = Rind::Html::A.new()
|
7
|
+
@b1 = Rind::Html::B.new()
|
8
|
+
@b2 = Rind::Html::B.new()
|
9
|
+
@a.children.push(@b1, @b2)
|
9
10
|
end
|
10
11
|
|
11
12
|
def test_insert_after
|
12
|
-
assert_equal(@
|
13
|
+
assert_equal(@a.children[1].insert_after('foo'), [@b1, @b2, 'foo'])
|
13
14
|
end
|
14
15
|
|
15
16
|
def test_insert_before
|
16
|
-
assert_equal(@
|
17
|
+
assert_equal(@a.children[1].insert_before('foo'), [@b1, 'foo', @b2])
|
17
18
|
end
|
18
19
|
|
19
20
|
def test_remove
|
20
|
-
assert_equal(@
|
21
|
-
assert(@
|
21
|
+
assert_equal(@a.children[1].remove, @b2)
|
22
|
+
assert(@a.children.empty?)
|
22
23
|
end
|
23
24
|
end
|
data/test/xml_test.rb
CHANGED
@@ -4,11 +4,11 @@ require 'rind'
|
|
4
4
|
class XmlTest < Test::Unit::TestCase
|
5
5
|
def test_to_s
|
6
6
|
# no children
|
7
|
-
a_tag = Rind::Xml::A.new()
|
7
|
+
a_tag = Rind::Xml::A.new()
|
8
8
|
assert_equal(a_tag.to_s, '<a />')
|
9
9
|
|
10
10
|
# with children
|
11
|
-
b_tag = Rind::Xml::B.new(:children => a_tag)
|
11
|
+
b_tag = Rind::Xml::B.new(:children => a_tag)
|
12
12
|
assert_equal(b_tag.to_s, '<b><a /></b>')
|
13
13
|
end
|
14
14
|
end
|
data/test/xpath_test.rb
CHANGED
@@ -3,28 +3,84 @@ require 'rind'
|
|
3
3
|
|
4
4
|
class XpathTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@
|
6
|
+
@a = Rind::Html::A.new
|
7
|
+
@b1 = Rind::Html::B.new(:attributes => {:id => '1', :class => '1'})
|
8
|
+
@b2 = Rind::Html::B.new(:attributes => {:id => '2', :class => '2'})
|
9
|
+
@b3 = Rind::Html::B.new(:attributes => {:id => '3', :type => 'text/css'})
|
10
|
+
@c1 = Rind::Html::C.new()
|
11
|
+
@c2 = Rind::Html::C.new()
|
12
|
+
@c3 = Rind::Html::C.new()
|
13
|
+
@comment = Rind::Comment.new('comment')
|
14
|
+
@pi = Rind::ProcessingInstruction.new('pi')
|
15
|
+
@text = Rind::Text.new('text')
|
16
|
+
@b1.children.push(@c1)
|
17
|
+
@b2.children.push(@c2, @c3)
|
18
|
+
@b3.children.push(@comment, @pi, @text)
|
19
|
+
@a.children.push(@b1, @b2, @b3)
|
10
20
|
end
|
11
21
|
|
12
22
|
def test_s
|
13
|
-
assert_equal(@
|
23
|
+
assert_equal(@c1.s('/a'), [@a])
|
14
24
|
|
15
|
-
|
16
|
-
assert_equal(@p_one.s('br[@class="1"]'), [@br_one])
|
25
|
+
assert_equal(@a.s('//c'), [@c1, @c2, @c3])
|
17
26
|
|
18
|
-
|
19
|
-
assert_equal(@p_one.s('br[2]'), [@br_two])
|
20
|
-
assert_equal(@p_one.s('br[position()=1]'), [@br_one])
|
21
|
-
assert_equal(@p_one.s('br[last()]'), [@br_three])
|
27
|
+
assert_equal(@c2.s('..'), [@b2] )
|
22
28
|
|
23
|
-
assert_equal(@
|
29
|
+
assert_equal(@c2.s('.'), [@c2] )
|
30
|
+
|
31
|
+
assert_equal(@a.s('foo'), [])
|
24
32
|
end
|
25
33
|
|
34
|
+
def test_s_axis
|
35
|
+
assert_equal(@c1.s('ancestor::*'), [@b1, @a])
|
36
|
+
|
37
|
+
assert_equal(@c1.s('ancestor-or-self::*'), [@c1, @b1, @a])
|
38
|
+
|
39
|
+
assert_equal(@a.s('child::*'), [@b1, @b2, @b3])
|
40
|
+
|
41
|
+
assert_equal(@a.s('descendant::*'), [@b1, @b2, @b3, @c1, @c2, @c3, @comment, @pi])
|
42
|
+
|
43
|
+
assert_equal(@a.s('descendant-or-self::*'), [@a, @b1, @b2, @b3, @c1, @c2, @c3, @comment, @pi])
|
44
|
+
|
45
|
+
assert_equal(@b2.s('following-sibling::*'), [@b3])
|
46
|
+
|
47
|
+
assert_equal(@b3.s('parent::*'), [@a])
|
48
|
+
|
49
|
+
assert_equal(@b2.s('preceding-sibling::*'), [@b1])
|
50
|
+
|
51
|
+
assert_equal(@a.s('self::*'), [@a])
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_s_node_test
|
55
|
+
assert_equal(@a.s('//*'), [@b1, @b2, @b3, @c1, @c2, @c3, @comment, @pi])
|
56
|
+
|
57
|
+
assert_equal(@a.s('//comment()'), [@comment])
|
58
|
+
|
59
|
+
assert_equal(@a.s('//node()'), [@b1, @b2, @b3, @c1, @c2, @c3, @comment, @pi, @text])
|
60
|
+
|
61
|
+
assert_equal(@a.s('//processing-instruction()'), [@pi])
|
62
|
+
|
63
|
+
assert_equal(@a.s('//text()'), [@text])
|
64
|
+
|
65
|
+
assert_equal(@a.s('b'), [@b1, @b2, @b3])
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_s_attribute
|
69
|
+
assert_equal(@a.s('b[@class="1"]'), [@b1])
|
70
|
+
|
71
|
+
assert_equal(@a.s('//b[@type="text/css"]'), [@b3])
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_s_position
|
75
|
+
assert_equal(@b2.s('c[2]'), [@c3])
|
76
|
+
|
77
|
+
assert_equal(@a.s('b[position()=1]'), [@b1])
|
78
|
+
|
79
|
+
assert_equal(@a.s('b[last()]'), [@b3])
|
80
|
+
end
|
81
|
+
|
26
82
|
def test_sf
|
27
|
-
assert_same(@
|
28
|
-
assert_nil(@
|
83
|
+
assert_same(@a.sf('b'), @b1)
|
84
|
+
assert_nil(@a.sf('foo'))
|
29
85
|
end
|
30
86
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rind
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 4
|
10
|
+
version: 0.1.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Aaron Lasseigne
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-06-
|
18
|
+
date: 2010-06-26 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -25,8 +25,9 @@ executables: []
|
|
25
25
|
|
26
26
|
extensions: []
|
27
27
|
|
28
|
-
extra_rdoc_files:
|
29
|
-
|
28
|
+
extra_rdoc_files:
|
29
|
+
- LICENSE
|
30
|
+
- CHANGELOG.rdoc
|
30
31
|
files:
|
31
32
|
- lib/rind/document.rb
|
32
33
|
- lib/rind/html.rb
|