rind 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|