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.
Files changed (3) hide show
  1. data/lib/sxrb/proxy.rb +55 -2
  2. data/spec/parser_spec.rb +168 -0
  3. 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
- def child(*args, &block)
9
- args.each do |tag|
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
@@ -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.1
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-06 00:00:00.000000000 Z
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: