sxrb 0.2.2 → 0.3.0
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 +14 -0
- data/lib/sxrb.rb +1 -0
- data/lib/sxrb/callbacks.rb +18 -4
- data/lib/sxrb/errors.rb +2 -0
- data/lib/sxrb/node.rb +11 -0
- data/lib/sxrb/parser.rb +76 -14
- data/lib/sxrb/proxy.rb +36 -18
- data/lib/sxrb/text_node.rb +6 -0
- data/spec/parser_spec.rb +111 -61
- data/spec/spec_helper.rb +8 -0
- metadata +5 -2
data/CHANGELOG
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
08 Aug 2012 (ver. 0.3.0)
|
2
|
+
* New constructors are available
|
3
|
+
* Parsing rules can be now reused
|
4
|
+
* YARD Documentation
|
5
|
+
|
6
|
+
07 Aug 2012 (ver. 0.2.2)
|
7
|
+
* Fixed gem dependencies
|
8
|
+
|
9
|
+
06 Aug 2012 (ver. 0.2.0)
|
10
|
+
* Added file and IO inputs support
|
11
|
+
* Project is now continously tested with Travis
|
12
|
+
|
13
|
+
05 Aug 2012 (ver. 0.1.0)
|
14
|
+
* Release!
|
data/lib/sxrb.rb
CHANGED
data/lib/sxrb/callbacks.rb
CHANGED
@@ -2,17 +2,25 @@ require 'libxml'
|
|
2
2
|
require 'sxrb/node'
|
3
3
|
require 'sxrb/text_node'
|
4
4
|
|
5
|
-
# This class provides callbacks for SAX API which are configured with sxrb DSL.
|
6
5
|
|
7
6
|
module SXRB
|
7
|
+
|
8
|
+
# This class provides callbacks for SAX API which are configured with sxrb
|
9
|
+
# DSL. It's behavior is configured by DSL via Proxy class objects, and should
|
10
|
+
# not be used outside of this scope. Currently it has only been tested with
|
11
|
+
# LibXML implementation of SAX, but set of method that object needs to
|
12
|
+
# provide is defined by standard, so using it with different backend should
|
13
|
+
# be automatic.
|
8
14
|
class Callbacks
|
9
15
|
#include LibXML::XML::SaxParser::VerboseCallbacks
|
10
16
|
include LibXML::XML::SaxParser::Callbacks
|
17
|
+
# @api private
|
11
18
|
def initialize
|
12
19
|
@stack = []
|
13
20
|
@rules_map = Hash.new {|h,k| h[k] = Rules.new}
|
14
21
|
end
|
15
22
|
|
23
|
+
# @api private
|
16
24
|
def on_start_element_ns(name, attributes, prefix, uri, namespaces)
|
17
25
|
Node.new(name, attributes, prefix, uri, namespaces).tap do |node|
|
18
26
|
@stack.push(node)
|
@@ -22,6 +30,7 @@ module SXRB
|
|
22
30
|
end
|
23
31
|
end
|
24
32
|
|
33
|
+
# @api private
|
25
34
|
def on_characters(chars)
|
26
35
|
if @stack.last.is_a? TextNode
|
27
36
|
@stack.last.append_text chars
|
@@ -34,6 +43,7 @@ module SXRB
|
|
34
43
|
end
|
35
44
|
end
|
36
45
|
|
46
|
+
# @api private
|
37
47
|
def on_end_element_ns(name, prefix, uri)
|
38
48
|
@stack.pop if @stack.last.is_a? TextNode
|
39
49
|
|
@@ -48,6 +58,7 @@ module SXRB
|
|
48
58
|
end
|
49
59
|
end
|
50
60
|
|
61
|
+
# @api private
|
51
62
|
def add_callback(type, rule_path, &block)
|
52
63
|
@rules_map[Regexp.new "^#{rule_path}$"].tap do |rules|
|
53
64
|
rules.rules[type] = block
|
@@ -55,9 +66,7 @@ module SXRB
|
|
55
66
|
end
|
56
67
|
end
|
57
68
|
|
58
|
-
#
|
59
|
-
# recursive
|
60
|
-
#
|
69
|
+
# @api private
|
61
70
|
def add_rule(rule, rule_path, options)
|
62
71
|
operator = options[:recursive] ? '.*' : ' '
|
63
72
|
new_rule = rule_path + operator + rule
|
@@ -66,23 +75,28 @@ module SXRB
|
|
66
75
|
|
67
76
|
private
|
68
77
|
|
78
|
+
# @api private
|
69
79
|
def invoke_callback(type, *args)
|
70
80
|
current_matching_rules.
|
71
81
|
map {|value| value.rules[type]}.
|
72
82
|
compact.each {|callback| callback.call(*args)}
|
73
83
|
end
|
74
84
|
|
85
|
+
# @api private
|
75
86
|
def current_matching_rules
|
76
87
|
@rules_map.each_pair.
|
77
88
|
select {|rule, value| current_rule_path =~ rule}.
|
78
89
|
map {|rule, value| value}
|
79
90
|
end
|
80
91
|
|
92
|
+
# @api private
|
81
93
|
def current_rule_path
|
82
94
|
@stack.map(&:name).join(' ')
|
83
95
|
end
|
84
96
|
end
|
85
97
|
|
98
|
+
# Internal class that is designed to keep rules of matching XML elements.
|
99
|
+
# @api private
|
86
100
|
class Rules
|
87
101
|
attr_accessor :rules, :recursive
|
88
102
|
def initialize
|
data/lib/sxrb/errors.rb
CHANGED
data/lib/sxrb/node.rb
CHANGED
@@ -1,16 +1,27 @@
|
|
1
1
|
module SXRB
|
2
|
+
# Node class is simple DOM-like element, which allows easy travesing through
|
3
|
+
# restricted part of document structure with #children and #parent methods.
|
2
4
|
class Node < Struct.new(:name, :attributes, :prefix, :uri, :namespaces, :parent)
|
3
5
|
attr_accessor :children
|
6
|
+
# Internal method used to build DOM-like structure.
|
7
|
+
# @api private
|
4
8
|
def initialize(*args, &block)
|
5
9
|
super(*args, &block)
|
6
10
|
@children = []
|
7
11
|
end
|
8
12
|
|
13
|
+
# Internal method used to build DOM-like structure.
|
14
|
+
# @api private
|
9
15
|
def append(node)
|
10
16
|
node.parent = self
|
11
17
|
@children << node
|
12
18
|
end
|
13
19
|
|
20
|
+
|
21
|
+
# Returns text content of a node (recursively), skipping all markup.
|
22
|
+
# @return [String]
|
23
|
+
# Text content of this node and all it's descendants is returned,
|
24
|
+
# concatenated.
|
14
25
|
def content
|
15
26
|
children.map {|child| child.is_a?(TextNode)? child.text : child.content}.flatten.join('')
|
16
27
|
end
|
data/lib/sxrb/parser.rb
CHANGED
@@ -2,28 +2,90 @@ require 'sxrb/callbacks'
|
|
2
2
|
require 'sxrb/proxy'
|
3
3
|
|
4
4
|
module SXRB
|
5
|
+
# Main class of gem, which allows parsing XML data.
|
5
6
|
class Parser
|
7
|
+
# Create parser object and parse provided input.
|
8
|
+
# @param [Filename, IO, String] input
|
9
|
+
# Data stream to be parsed.
|
10
|
+
# @option opts [Symbol] :mode (:string)
|
11
|
+
# Instructs SXRB how to treat input parameter. Possible values are:
|
12
|
+
# :string, :file, :io. Please note, that in case of :file mode
|
13
|
+
# input should be filename.
|
14
|
+
# @deprecated
|
15
|
+
# This method should not be used anymore. In version 1.0 it will work
|
16
|
+
# completely different so it is preferable to migrate to use parse_*
|
17
|
+
# methods right now.
|
6
18
|
def initialize(input, opts = {}, &block)
|
7
19
|
raise ArgumentError.new("Block expected") if block.nil?
|
8
|
-
|
20
|
+
case opts[:mode]
|
21
|
+
when :file
|
22
|
+
self.class.parse_file(input, &block)
|
23
|
+
when :io
|
24
|
+
self.class.parse_io(input, &block)
|
25
|
+
else
|
26
|
+
self.class.parse_string(input, &block)
|
27
|
+
end
|
28
|
+
end
|
9
29
|
|
10
|
-
|
30
|
+
# Define set of reusable rules for SXRB parser.
|
31
|
+
# @yield Proxy
|
32
|
+
# See Proxy documentation for details on available methods and defining
|
33
|
+
# rules.
|
34
|
+
# @return [Callbacks]
|
35
|
+
# Set of rules which can be feeded to parse_* methods.
|
36
|
+
def self.define_rules(&block)
|
37
|
+
Callbacks.new.tap do |cb|
|
38
|
+
yield Proxy.new(cb)
|
39
|
+
end
|
40
|
+
end
|
11
41
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
42
|
+
# Parse string containing XML.
|
43
|
+
# @param [String] string
|
44
|
+
# Input string
|
45
|
+
# @param [optional, Callbacks] callbacks
|
46
|
+
# Set of rules generated by define_rules.
|
47
|
+
# @yield [Proxy]
|
48
|
+
# If callbacks parameter is not provided rules have to be defined directly in provided block.
|
49
|
+
# @return [nil]
|
50
|
+
def self.parse_string(string, callbacks = nil, &block)
|
51
|
+
raise ArgumentError unless !!callbacks ^ !!block
|
52
|
+
LibXML::XML::SaxParser.string(string).tap do |parser|
|
53
|
+
parser.callbacks = callbacks || define_rules(&block)
|
54
|
+
parser.parse
|
55
|
+
end
|
56
|
+
nil
|
57
|
+
end
|
20
58
|
|
21
|
-
|
22
|
-
|
59
|
+
# Parse file containing XML.
|
60
|
+
# @param [String] filename
|
61
|
+
# Path to file to be parsed.
|
62
|
+
# @param [optional, Callbacks] callbacks
|
63
|
+
# Set of rules generated by define_rules.
|
64
|
+
# @yield [Proxy]
|
65
|
+
# If callbacks parameter is not provided rules have to be defined directly in provided block.
|
66
|
+
# @return [nil]
|
67
|
+
def self.parse_file(filename, callbacks = nil, &block)
|
68
|
+
raise ArgumentError unless !!callbacks ^ !!block
|
69
|
+
LibXML::XML::SaxParser.file(filename).tap do |parser|
|
70
|
+
parser.callbacks = callbacks || define_rules(&block)
|
71
|
+
parser.parse
|
23
72
|
end
|
73
|
+
end
|
24
74
|
|
25
|
-
|
26
|
-
|
75
|
+
# Parse IO containing XML.
|
76
|
+
# @param [IO] io
|
77
|
+
# Path to stream to be parsed.
|
78
|
+
# @param [optional, Callbacks] callbacks
|
79
|
+
# Set of rules generated by define_rules.
|
80
|
+
# @yield [Proxy]
|
81
|
+
# If callbacks parameter is not provided rules have to be defined directly in provided block.
|
82
|
+
# @return [nil]
|
83
|
+
def self.parse_io(io, callbacks = nil, &block)
|
84
|
+
raise ArgumentError unless !!callbacks ^ !!block
|
85
|
+
LibXML::XML::SaxParser.io(io).tap do |parser|
|
86
|
+
parser.callbacks = callbacks || define_rules(&block)
|
87
|
+
parser.parse
|
88
|
+
end
|
27
89
|
end
|
28
90
|
end
|
29
91
|
end
|
data/lib/sxrb/proxy.rb
CHANGED
@@ -1,18 +1,25 @@
|
|
1
1
|
module SXRB
|
2
|
+
# Objects of Proxy class are part of SXRB DSL and their methods are meant to
|
3
|
+
# be used to define set of rules needed to parse XML document. They have no
|
4
|
+
# other meaning and should not be used outside of that scope.
|
5
|
+
# @api public
|
2
6
|
class Proxy
|
7
|
+
# Proxy objects are generated by the SXRB itself, and are passed to blocks
|
8
|
+
# to be used as DSL. They should not be created in any other context.
|
9
|
+
# Implementation might change without prior notice.
|
10
|
+
#
|
3
11
|
# @api private
|
4
12
|
def initialize(callback_tree, current_path = '')
|
5
13
|
@callback_tree = callback_tree
|
6
14
|
@current_path = current_path
|
7
15
|
end
|
8
16
|
|
9
|
-
# Defines child (a direct descendant) of an element defined in current.
|
10
|
-
#
|
11
|
-
# @param [String] *tags
|
17
|
+
# Defines child (a direct descendant) of an element defined in current block.
|
18
|
+
# @param [String] tags
|
12
19
|
# names of tags that should be matched
|
13
20
|
#
|
14
21
|
# @yield [Proxy]
|
15
|
-
# block receives Proxy element representing matched elements
|
22
|
+
# block receives Proxy element representing matched elements.
|
16
23
|
#
|
17
24
|
# @return [nil]
|
18
25
|
#
|
@@ -28,19 +35,19 @@ module SXRB
|
|
28
35
|
end
|
29
36
|
|
30
37
|
# Defines descendant of an element defined in current block.
|
31
|
-
# @param [String]
|
38
|
+
# @param [String] tags
|
32
39
|
# names of tags that should be matched
|
33
40
|
#
|
34
41
|
# @yield [Proxy]
|
35
|
-
# block receives Proxy element representing matched elements
|
42
|
+
# block receives Proxy element representing matched elements.
|
36
43
|
#
|
37
44
|
# @return [nil]
|
38
45
|
#
|
39
46
|
# @api public
|
40
47
|
#
|
41
|
-
# @todo Add Regexp and other selectors support in addition to
|
42
|
-
def descendant(*
|
43
|
-
|
48
|
+
# @todo Add Regexp and other selectors support in addition to strings.
|
49
|
+
def descendant(*tags, &block)
|
50
|
+
tags.each do |tag|
|
44
51
|
@callback_tree.add_rule(tag, @current_path, :recursive => true).tap do |new_path|
|
45
52
|
block.call(Proxy.new(@callback_tree, new_path))
|
46
53
|
end
|
@@ -49,21 +56,28 @@ module SXRB
|
|
49
56
|
|
50
57
|
# Defines callback method invoked when matching element is completely
|
51
58
|
# parsed.
|
52
|
-
#
|
59
|
+
#
|
60
|
+
# @yield [Node]
|
61
|
+
# block receives whole parsed element with children.
|
53
62
|
#
|
54
63
|
# @api public
|
55
64
|
#
|
56
|
-
# @
|
57
|
-
#
|
65
|
+
# @return [nil]
|
66
|
+
#
|
67
|
+
# @note
|
68
|
+
# `on_element` should not be used for items that are expected to have
|
69
|
+
# large node subtrees.
|
58
70
|
def on_element(&block)
|
59
71
|
@callback_tree.add_callback(:element, @current_path, &block)
|
60
72
|
end
|
61
73
|
|
62
74
|
# Defines a callback that is invoked whenever start tag is encountered.
|
63
75
|
#
|
64
|
-
# @yield [Node]
|
65
|
-
#
|
76
|
+
# @yield [Node]
|
77
|
+
# block receives parsed node without any nested elements. All inline
|
78
|
+
# attributes are available though.
|
66
79
|
#
|
80
|
+
# @return [nil]
|
67
81
|
# @api public
|
68
82
|
def on_start(&block)
|
69
83
|
@callback_tree.add_callback(:start, @current_path, &block)
|
@@ -72,8 +86,10 @@ module SXRB
|
|
72
86
|
# Defines a callback that is invoked whenever anonymous text node within
|
73
87
|
# self is encountered.
|
74
88
|
#
|
75
|
-
# @yield [String]
|
76
|
-
#
|
89
|
+
# @yield [String]
|
90
|
+
# block receives raw content of parsed data in form of string object.
|
91
|
+
#
|
92
|
+
# @return [nil]
|
77
93
|
#
|
78
94
|
# @api public
|
79
95
|
def on_characters(&block)
|
@@ -82,9 +98,11 @@ module SXRB
|
|
82
98
|
|
83
99
|
# Defines a callback that is invoked whenever end tag is encountered.
|
84
100
|
#
|
85
|
-
# @yield [Node]
|
86
|
-
#
|
101
|
+
# @yield [Node]
|
102
|
+
# block receives parsed node without any nested elements. All inline
|
103
|
+
# attributes are available though.
|
87
104
|
#
|
105
|
+
# @return [nil]
|
88
106
|
# @api public
|
89
107
|
def on_end(&block)
|
90
108
|
@callback_tree.add_callback(:end, @current_path, &block)
|
data/lib/sxrb/text_node.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
module SXRB
|
2
|
+
# Class representing special case of DOM nodes which contain only text, and
|
3
|
+
# don't represent any particular element.
|
2
4
|
class TextNode < Node
|
5
|
+
# @api private
|
3
6
|
def initialize(text)
|
4
7
|
@text = text || ""
|
5
8
|
end
|
6
9
|
|
10
|
+
# @api private
|
7
11
|
def append_text(text)
|
8
12
|
@text << text
|
9
13
|
end
|
10
14
|
|
15
|
+
# Accessor for text data kept in TextNode object.
|
16
|
+
# @return [String]
|
11
17
|
def text
|
12
18
|
@text
|
13
19
|
end
|
data/spec/parser_spec.rb
CHANGED
@@ -1,92 +1,125 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe SXRB::Parser do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
context 'constructors' do
|
5
|
+
it 'should fail when created without block' do
|
6
|
+
expect {
|
7
|
+
SXRB::Parser.new("<xmlstring/>")
|
8
|
+
}.to raise_error(ArgumentError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'defined rules should be reusable' do
|
12
|
+
@handler = double('handler')
|
13
|
+
@handler.should_receive(:msg).twice
|
14
|
+
rules = SXRB::Parser.define_rules do |root|
|
15
|
+
root.child("el") do |el|
|
16
|
+
el.on_element {@handler.msg}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
SXRB::Parser.parse_string('<el></el>', rules)
|
20
|
+
SXRB::Parser.parse_string('<el></el>', rules)
|
21
|
+
end
|
8
22
|
end
|
9
23
|
|
10
|
-
context '
|
11
|
-
|
12
|
-
handler = double('handler')
|
13
|
-
|
24
|
+
context 'matchers' do
|
25
|
+
before(:each) do
|
26
|
+
@handler = double('handler')
|
27
|
+
end
|
14
28
|
|
29
|
+
it 'should call defined start callback for child element' do
|
30
|
+
@handler.should_receive(:msg).once
|
15
31
|
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
16
32
|
xml.child 'testelement' do |test_element|
|
17
|
-
test_element.on_start
|
18
|
-
handler.msg
|
19
|
-
end
|
33
|
+
test_element.on_start {@handler.msg}
|
20
34
|
end
|
21
35
|
end
|
22
36
|
end
|
23
37
|
|
24
38
|
it 'should call defined end callback for child element' do
|
25
|
-
handler
|
26
|
-
handler.should_receive(:msg).once
|
27
|
-
|
39
|
+
@handler.should_receive(:msg).once
|
28
40
|
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
29
41
|
xml.child 'testelement' do |test_element|
|
30
|
-
test_element.on_end
|
31
|
-
handler.msg
|
32
|
-
end
|
42
|
+
test_element.on_end {@handler.msg}
|
33
43
|
end
|
34
44
|
end
|
35
45
|
end
|
36
46
|
|
37
47
|
it 'should call defined characters callback for child element' do
|
38
|
-
handler
|
39
|
-
handler.should_receive(:msg).once
|
40
|
-
|
48
|
+
@handler.should_receive(:msg).once
|
41
49
|
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
42
50
|
xml.child 'testelement' do |test_element|
|
43
|
-
test_element.on_characters
|
44
|
-
handler.msg
|
45
|
-
end
|
51
|
+
test_element.on_characters {@handler.msg}
|
46
52
|
end
|
47
53
|
end
|
48
54
|
end
|
49
55
|
|
50
56
|
|
51
57
|
it 'should call defined element callback for child element' do
|
52
|
-
handler
|
53
|
-
handler.should_receive(:msg).once
|
54
|
-
|
58
|
+
@handler.should_receive(:msg).once
|
55
59
|
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
56
60
|
xml.child 'testelement' do |test_element|
|
57
|
-
test_element.on_element
|
58
|
-
handler.msg
|
59
|
-
end
|
61
|
+
test_element.on_element {@handler.msg}
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
63
65
|
|
64
66
|
it 'should call defined element callback for child element only' do
|
65
|
-
handler
|
66
|
-
handler.should_receive(:msg).once
|
67
|
-
|
67
|
+
@handler.should_receive(:msg).once
|
68
68
|
SXRB::Parser.new("<testelement><testelement>content</testelement></testelement>") do |xml|
|
69
69
|
xml.child 'testelement' do |test_element|
|
70
|
-
test_element.on_element
|
71
|
-
handler.msg
|
72
|
-
end
|
70
|
+
test_element.on_element {@handler.msg}
|
73
71
|
end
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
77
75
|
it 'should call defined element callback for all descendants' do
|
78
|
-
handler
|
79
|
-
handler.should_receive(:msg).twice
|
80
|
-
|
76
|
+
@handler.should_receive(:msg).twice
|
81
77
|
SXRB::Parser.new("<testelement><testelement>content</testelement></testelement>") do |xml|
|
82
78
|
xml.descendant 'testelement' do |test_element|
|
83
|
-
test_element.on_element
|
84
|
-
|
85
|
-
|
79
|
+
test_element.on_element {@handler.msg}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should call callback for element regardless of nested elements' do
|
85
|
+
@handler.should_receive(:msg).once
|
86
|
+
SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
|
87
|
+
xml.child 'testelement' do |test_element|
|
88
|
+
test_element.on_element {@handler.msg}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should not invoke callback for child which isn\'t direct descendant' do
|
94
|
+
@handler.should_not_receive(:msg)
|
95
|
+
SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
|
96
|
+
xml.child 'a' do |a|
|
97
|
+
a.on_element {@handler.msg}
|
86
98
|
end
|
87
99
|
end
|
88
100
|
end
|
89
101
|
|
102
|
+
it 'should not find element with non-matching name' do
|
103
|
+
@handler.should_not_receive(:msg)
|
104
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
105
|
+
xml.child 'othername' do |test_element|
|
106
|
+
test_element.on_element {@handler.msg}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should find element by regexp' do
|
112
|
+
pending "feature not ready yet"
|
113
|
+
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
114
|
+
xml.child /testel/ do |test_element|
|
115
|
+
test_element.on_element {@handler.msg}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'passed values' do
|
122
|
+
|
90
123
|
it 'should pass empty hash to callback when no attributes are given' do
|
91
124
|
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
92
125
|
xml.child 'testelement' do |test_element|
|
@@ -97,32 +130,51 @@ describe SXRB::Parser do
|
|
97
130
|
end
|
98
131
|
end
|
99
132
|
|
100
|
-
it 'should pass
|
101
|
-
SXRB::Parser.new(
|
133
|
+
it 'should pass attributes properly to on_start callback' do
|
134
|
+
SXRB::Parser.new('<testelement foo="bar">content</testelement>') do |xml|
|
135
|
+
xml.child 'testelement' do |test_element|
|
136
|
+
test_element.on_start do |element|
|
137
|
+
element.attributes.should == {'foo' => 'bar'}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should pass attributes properly to on_element callback' do
|
144
|
+
SXRB::Parser.new('<testelement foo="bar">content</testelement>') do |xml|
|
102
145
|
xml.child 'testelement' do |test_element|
|
103
146
|
test_element.on_element do |element|
|
104
|
-
element.
|
147
|
+
element.attributes.should == {'foo' => 'bar'}
|
105
148
|
end
|
106
149
|
end
|
107
150
|
end
|
108
151
|
end
|
109
152
|
|
110
|
-
it 'should
|
111
|
-
SXRB::Parser.new(
|
112
|
-
xml.child '
|
113
|
-
test_element.
|
114
|
-
|
153
|
+
it 'should pass attributes properly to on_end callback' do
|
154
|
+
SXRB::Parser.new('<testelement foo="bar">content</testelement>') do |xml|
|
155
|
+
xml.child 'testelement' do |test_element|
|
156
|
+
test_element.on_end do |element|
|
157
|
+
element.attributes.should == {'foo' => 'bar'}
|
115
158
|
end
|
116
159
|
end
|
117
160
|
end
|
118
161
|
end
|
119
162
|
|
120
|
-
it 'should
|
121
|
-
|
163
|
+
it 'should pass concatenated content' do
|
164
|
+
SXRB::Parser.new("<testelement><a>con</a>tent</testelement>") do |xml|
|
165
|
+
xml.child 'testelement' do |test_element|
|
166
|
+
test_element.on_element do |element|
|
167
|
+
element.content == 'content'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should pass value properly to callback to on_element' do
|
122
174
|
SXRB::Parser.new("<testelement>content</testelement>") do |xml|
|
123
|
-
xml.child
|
124
|
-
test_element.on_element do |
|
125
|
-
|
175
|
+
xml.child 'testelement' do |test_element|
|
176
|
+
test_element.on_element do |element|
|
177
|
+
element.content == 'content'
|
126
178
|
end
|
127
179
|
end
|
128
180
|
end
|
@@ -133,20 +185,18 @@ describe SXRB::Parser do
|
|
133
185
|
xml.child 'testelement' do |test_element|
|
134
186
|
test_element.child 'a' do |a|
|
135
187
|
a.on_element do |element|
|
136
|
-
element.
|
188
|
+
element.content == 'a-content'
|
137
189
|
end
|
138
190
|
end
|
139
191
|
end
|
140
192
|
end
|
141
193
|
end
|
142
194
|
|
143
|
-
it 'should
|
144
|
-
handler = double('handler')
|
145
|
-
handler.should_receive(:msg).once
|
195
|
+
it 'should pass nested elements content on_element callback' do
|
146
196
|
SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
|
147
197
|
xml.child 'testelement' do |test_element|
|
148
|
-
test_element.on_element do |
|
149
|
-
|
198
|
+
test_element.on_element do |node|
|
199
|
+
node.content.should == 'a-content'
|
150
200
|
end
|
151
201
|
end
|
152
202
|
end
|
@@ -158,7 +208,7 @@ describe SXRB::Parser do
|
|
158
208
|
test_element.on_element do |element|
|
159
209
|
element.children.first.tap do |a|
|
160
210
|
a.name.should == 'a'
|
161
|
-
a.
|
211
|
+
a.content.should == 'a-content'
|
162
212
|
end
|
163
213
|
end
|
164
214
|
end
|
data/spec/spec_helper.rb
ADDED
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.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: libxml-ruby
|
@@ -40,7 +40,9 @@ files:
|
|
40
40
|
- lib/sxrb/errors.rb
|
41
41
|
- lib/sxrb/proxy.rb
|
42
42
|
- lib/sxrb.rb
|
43
|
+
- CHANGELOG
|
43
44
|
- spec/parser_spec.rb
|
45
|
+
- spec/spec_helper.rb
|
44
46
|
homepage: http://rubygems.org/gems/sxrb
|
45
47
|
licenses:
|
46
48
|
- MIT
|
@@ -68,4 +70,5 @@ specification_version: 3
|
|
68
70
|
summary: Smart XML parser
|
69
71
|
test_files:
|
70
72
|
- spec/parser_spec.rb
|
73
|
+
- spec/spec_helper.rb
|
71
74
|
has_rdoc:
|