sxrb 0.2.1 → 0.2.2
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/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:
|