sxrb 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/sxrb/proxy.rb +55 -2
- data/spec/parser_spec.rb +168 -0
- metadata +24 -5
data/lib/sxrb/proxy.rb
CHANGED
@@ -1,18 +1,44 @@
|
|
1
1
|
module SXRB
|
2
2
|
class Proxy
|
3
|
+
# @api private
|
3
4
|
def initialize(callback_tree, current_path = '')
|
4
5
|
@callback_tree = callback_tree
|
5
6
|
@current_path = current_path
|
6
7
|
end
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
# Defines child (a direct descendant) of an element defined in current.
|
10
|
+
# block.
|
11
|
+
# @param [String] *tags
|
12
|
+
# names of tags that should be matched
|
13
|
+
#
|
14
|
+
# @yield [Proxy]
|
15
|
+
# block receives Proxy element representing matched elements
|
16
|
+
#
|
17
|
+
# @return [nil]
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
#
|
21
|
+
# @todo Add Regexp and other selectors support in addition to Strings.
|
22
|
+
def child(*tags, &block)
|
23
|
+
tags.each do |tag|
|
10
24
|
@callback_tree.add_rule(tag, @current_path, :recursive => false).tap do |new_path|
|
11
25
|
block.call(Proxy.new(@callback_tree, new_path))
|
12
26
|
end
|
13
27
|
end
|
14
28
|
end
|
15
29
|
|
30
|
+
# Defines descendant of an element defined in current block.
|
31
|
+
# @param [String] *tags
|
32
|
+
# names of tags that should be matched
|
33
|
+
#
|
34
|
+
# @yield [Proxy]
|
35
|
+
# block receives Proxy element representing matched elements
|
36
|
+
#
|
37
|
+
# @return [nil]
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
#
|
41
|
+
# @todo Add Regexp and other selectors support in addition to Strings.
|
16
42
|
def descendant(*args, &block)
|
17
43
|
args.each do |tag|
|
18
44
|
@callback_tree.add_rule(tag, @current_path, :recursive => true).tap do |new_path|
|
@@ -21,18 +47,45 @@ module SXRB
|
|
21
47
|
end
|
22
48
|
end
|
23
49
|
|
50
|
+
# Defines callback method invoked when matching element is completely
|
51
|
+
# parsed.
|
52
|
+
# @yield [Node] block receives whole parsed element with children.
|
53
|
+
#
|
54
|
+
# @api public
|
55
|
+
#
|
56
|
+
# @note `on_element` should not be used for items that are expected to have
|
57
|
+
# large node subtrees.
|
24
58
|
def on_element(&block)
|
25
59
|
@callback_tree.add_callback(:element, @current_path, &block)
|
26
60
|
end
|
27
61
|
|
62
|
+
# Defines a callback that is invoked whenever start tag is encountered.
|
63
|
+
#
|
64
|
+
# @yield [Node] block receives parsed node without any nested elements. All
|
65
|
+
# inline attributes are available though.
|
66
|
+
#
|
67
|
+
# @api public
|
28
68
|
def on_start(&block)
|
29
69
|
@callback_tree.add_callback(:start, @current_path, &block)
|
30
70
|
end
|
31
71
|
|
72
|
+
# Defines a callback that is invoked whenever anonymous text node within
|
73
|
+
# self is encountered.
|
74
|
+
#
|
75
|
+
# @yield [String] block receives raw content of parsed data in form of
|
76
|
+
# String object.
|
77
|
+
#
|
78
|
+
# @api public
|
32
79
|
def on_characters(&block)
|
33
80
|
@callback_tree.add_callback(:characters, @current_path, &block)
|
34
81
|
end
|
35
82
|
|
83
|
+
# Defines a callback that is invoked whenever end tag is encountered.
|
84
|
+
#
|
85
|
+
# @yield [Node] block receives parsed node without any nested elements. All
|
86
|
+
# inline attributes are available though.
|
87
|
+
#
|
88
|
+
# @api public
|
36
89
|
def on_end(&block)
|
37
90
|
@callback_tree.add_callback(:end, @current_path, &block)
|
38
91
|
end
|
data/spec/parser_spec.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SXRB::Parser do
|
4
|
+
it 'should fail when created without block' do
|
5
|
+
expect {
|
6
|
+
SXRB::Parser.new("<xmlstring/>")
|
7
|
+
}.to raise_error(ArgumentError)
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'callbacks' do
|
11
|
+
it 'should call defined start callback for child element' do
|
12
|
+
handler = double('handler')
|
13
|
+
handler.should_receive(:msg).once
|
14
|
+
|
15
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
16
|
+
xml.child 'testelement' do |test_element|
|
17
|
+
test_element.on_start do |element|
|
18
|
+
handler.msg
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should call defined end callback for child element' do
|
25
|
+
handler = double('handler')
|
26
|
+
handler.should_receive(:msg).once
|
27
|
+
|
28
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
29
|
+
xml.child 'testelement' do |test_element|
|
30
|
+
test_element.on_end do |element|
|
31
|
+
handler.msg
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should call defined characters callback for child element' do
|
38
|
+
handler = double('handler')
|
39
|
+
handler.should_receive(:msg).once
|
40
|
+
|
41
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
42
|
+
xml.child 'testelement' do |test_element|
|
43
|
+
test_element.on_characters do |element|
|
44
|
+
handler.msg
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
it 'should call defined element callback for child element' do
|
52
|
+
handler = double('handler')
|
53
|
+
handler.should_receive(:msg).once
|
54
|
+
|
55
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
56
|
+
xml.child 'testelement' do |test_element|
|
57
|
+
test_element.on_element do |element|
|
58
|
+
handler.msg
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should call defined element callback for child element only' do
|
65
|
+
handler = double('handler')
|
66
|
+
handler.should_receive(:msg).once
|
67
|
+
|
68
|
+
SXRB::Parser.new("<testelement><testelement>content</testelement></testelement>") do |xml|
|
69
|
+
xml.child 'testelement' do |test_element|
|
70
|
+
test_element.on_element do |element|
|
71
|
+
handler.msg
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should call defined element callback for all descendants' do
|
78
|
+
handler = double('handler')
|
79
|
+
handler.should_receive(:msg).twice
|
80
|
+
|
81
|
+
SXRB::Parser.new("<testelement><testelement>content</testelement></testelement>") do |xml|
|
82
|
+
xml.descendant 'testelement' do |test_element|
|
83
|
+
test_element.on_element do |element|
|
84
|
+
handler.msg
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should pass empty hash to callback when no attributes are given' do
|
91
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
92
|
+
xml.child 'testelement' do |test_element|
|
93
|
+
test_element.on_element do |element|
|
94
|
+
element.attributes.should == {}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should pass value properly to callback to on_element' do
|
101
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
102
|
+
xml.child 'testelement' do |test_element|
|
103
|
+
test_element.on_element do |element|
|
104
|
+
element.children.first.text == 'content'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should not find element with non-matching name' do
|
111
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
112
|
+
xml.child 'othername' do |test_element|
|
113
|
+
test_element.on_element do |attrs, value|
|
114
|
+
value.should == 'content'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should find element by regexp' do
|
121
|
+
pending "feature not ready yet"
|
122
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
123
|
+
xml.child /testel/ do |test_element|
|
124
|
+
test_element.on_element do |attrs, value|
|
125
|
+
value.should == 'content'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should find nested element' do
|
132
|
+
SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
|
133
|
+
xml.child 'testelement' do |test_element|
|
134
|
+
test_element.child 'a' do |a|
|
135
|
+
a.on_element do |element|
|
136
|
+
element.children.first.text == 'a-content'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should call callback for element regardless of nested elements' do
|
144
|
+
handler = double('handler')
|
145
|
+
handler.should_receive(:msg).once
|
146
|
+
SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
|
147
|
+
xml.child 'testelement' do |test_element|
|
148
|
+
test_element.on_element do |element|
|
149
|
+
handler.msg
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should pass nested elements to on_element callback' do
|
156
|
+
SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
|
157
|
+
xml.child 'testelement' do |test_element|
|
158
|
+
test_element.on_element do |element|
|
159
|
+
element.children.first.tap do |a|
|
160
|
+
a.name.should == 'a'
|
161
|
+
a.children.first.text.should == 'a-content'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sxrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
13
|
-
dependencies:
|
12
|
+
date: 2012-08-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: libxml-ruby
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.3.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.3.3
|
14
30
|
description: Robust XML parser that allows defining desired behavior with fancy DSL
|
15
31
|
email:
|
16
32
|
executables: []
|
@@ -24,8 +40,10 @@ files:
|
|
24
40
|
- lib/sxrb/errors.rb
|
25
41
|
- lib/sxrb/proxy.rb
|
26
42
|
- lib/sxrb.rb
|
43
|
+
- spec/parser_spec.rb
|
27
44
|
homepage: http://rubygems.org/gems/sxrb
|
28
|
-
licenses:
|
45
|
+
licenses:
|
46
|
+
- MIT
|
29
47
|
post_install_message:
|
30
48
|
rdoc_options: []
|
31
49
|
require_paths:
|
@@ -48,5 +66,6 @@ rubygems_version: 1.8.21
|
|
48
66
|
signing_key:
|
49
67
|
specification_version: 3
|
50
68
|
summary: Smart XML parser
|
51
|
-
test_files:
|
69
|
+
test_files:
|
70
|
+
- spec/parser_spec.rb
|
52
71
|
has_rdoc:
|