saxy 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 145b19ea70344eb97cb37dab58b172d07766a654
4
- data.tar.gz: 9b0a3482befc1f5270f8bfe5665a68b4cc0a87f4
3
+ metadata.gz: 52a8b74342fe631ae2787bd38fedcb3600b24730
4
+ data.tar.gz: 37ef8a7e143494b48ba13c3d7470c84e459d0bf7
5
5
  SHA512:
6
- metadata.gz: 229a5ceede847656383a9b86a8521d17030c97329233cc36a0a32f6beceb2efcacff06a9e2d030a05c81014f41b9dc3f7c31f83b5cbce933827136149e48bab8
7
- data.tar.gz: dd980f2f3fc39731e19776316bde8f16abb8f28be32d7f036cfca65db6867fa7dd1d7362360a96e3759b2f389a6e48e6aa3ab88df568ebfb3334174e9492af6c
6
+ metadata.gz: 468d1551a3fdafc0c0b37cdffb5482f1ecd5cf2fac2c8f63b23c7d75dc38c1d13b47ac8a7d195b8031251d62a5ea13492674cf418f25cf732d30e073a8f99f9b
7
+ data.tar.gz: d026bfaa8643b1eeb12ce00eecc13e4f1d27e531308706e14d05f1a9bc2d22755a5e2479482d5024ce298732373ea62498314d083fe4a2fa2aa8e5da3399c6a9
@@ -2,6 +2,7 @@ script: "bundle exec rspec ./spec/"
2
2
  sudo: false
3
3
  language: ruby
4
4
  rvm:
5
+ - 2.5
5
6
  - 2.4
6
7
  - 2.3
7
8
  - 2.2
@@ -1,5 +1,10 @@
1
1
  # Saxy Changelog
2
2
 
3
+ ## 0.7.1
4
+
5
+ * Fixed whitespace stripping from elements' contents, now only leading and trailing whitespace is stripped (reported by @wzcolon, thanks!).
6
+ * Added `error_handler` option to make it possible to handle errors on-the-fly instead of raising them.
7
+
3
8
  ## 0.7.0
4
9
 
5
10
  * [BREAKING] Yielded hashes now have strings as keys instead of symbols (performance and security fix).
data/README.md CHANGED
@@ -64,6 +64,14 @@ end
64
64
  * `encoding` - Forces the parser to work in given encoding
65
65
  * `recovery` - Should this parser recover from structural errors? It will not stop processing file on structural errors if set to `true`.
66
66
  * `replace_entities` - Should this parser replace entities? `&` will get converted to `&` if set to `true`.
67
+ * `error_handler` - If set to a callable, parser will call it with any error it encounters instead of raising exceptions.
68
+
69
+ Combination of `error_handler` and `recovery` options allows for continued processing when encountering recoverable errors (e.g. unescaped [predefined entities](https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined_entities_in_XML)).
70
+
71
+ ```ruby
72
+ error_handler = proc { |e| $stderr.puts "#{e.message} at line #{e.context.line}, column #{e.context.column}." }
73
+ Saxy.parse(path_or_io, object_tag, error_handler: error_handler, recovery: true) { ... }
74
+ ```
67
75
 
68
76
  ## Example
69
77
 
@@ -1,6 +1,6 @@
1
1
  module Saxy
2
2
  class Element
3
- attr_reader :attributes, :value
3
+ attr_reader :attributes
4
4
 
5
5
  def initialize
6
6
  @attributes = {}
@@ -9,23 +9,30 @@ module Saxy
9
9
 
10
10
  def set_attribute(name, value)
11
11
  name = attribute_name(name)
12
+
12
13
  attributes[name] ||= []
13
14
  attributes[name] << value
14
15
  end
15
16
 
16
17
  def append_value(string)
17
- unless (string = string.strip).empty?
18
+ if @value || !string.strip.empty?
18
19
  @value ||= ""
19
20
  @value << string
20
21
  end
21
22
  end
22
23
 
24
+ def value
25
+ @value && @value.strip
26
+ end
27
+
23
28
  def to_h
24
29
  return value unless attributes.any?
30
+
25
31
  data = attributes.reduce({}) do |memo, (name, value)|
26
32
  memo[name] = value.size == 1 ? value.first : value
27
33
  memo
28
34
  end
35
+
29
36
  data["contents"] = value
30
37
  data
31
38
  end
@@ -37,12 +44,11 @@ module Saxy
37
44
  private
38
45
 
39
46
  def underscore(word)
40
- word = word.dup
41
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
42
- word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
43
- word.tr!("-", "_")
44
- word.downcase!
45
47
  word
48
+ .gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
49
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
50
+ .tr("-", "_")
51
+ .downcase
46
52
  end
47
53
  end
48
54
  end
@@ -41,6 +41,7 @@ module Saxy
41
41
 
42
42
  def end_element(tag)
43
43
  tags.pop
44
+
44
45
  if element = elements.pop
45
46
  object = element.to_h
46
47
 
@@ -61,7 +62,13 @@ module Saxy
61
62
  end
62
63
 
63
64
  def error(message)
64
- raise ParsingError.new(message, context)
65
+ error = ParsingError.new(message, context)
66
+
67
+ if options[:error_handler].respond_to?(:call)
68
+ options[:error_handler].call(error)
69
+ else
70
+ raise error
71
+ end
65
72
  end
66
73
 
67
74
  def current_element
@@ -73,8 +80,7 @@ module Saxy
73
80
 
74
81
  @callback = blk
75
82
 
76
- args = [self, options[:encoding]].compact
77
-
83
+ args = [self, options[:encoding]].compact
78
84
  parser = Nokogiri::XML::SAX::Parser.new(*args)
79
85
 
80
86
  if @object.respond_to?(:read) && @object.respond_to?(:close)
@@ -1,3 +1,3 @@
1
1
  module Saxy
2
- VERSION = "0.7.0"
2
+ VERSION = "0.7.1"
3
3
  end
@@ -3,7 +3,7 @@
3
3
  <products>
4
4
  <product>
5
5
  <uid>FFCF177</uid>
6
- <name>No closing tag...
6
+ <name>Unescaped & ampersand</name>
7
7
  </product>
8
8
  </products>
9
9
  </webstore>
@@ -8,10 +8,12 @@ describe Saxy::Element do
8
8
  expect(element.value).to be_nil
9
9
  end
10
10
 
11
- it "should append stripped value" do
12
- element.append_value(" foo ")
13
- element.append_value(" bar ")
14
- expect(element.value).to eq("foobar")
11
+ it "should strip leading and trailing whitespace" do
12
+ element.append_value(" one two ")
13
+ element.append_value("&")
14
+ element.append_value(" three\nfour")
15
+ element.append_value("\t\t")
16
+ expect(element.value).to eq("one two & three\nfour")
15
17
  end
16
18
 
17
19
  it "should dump as string when no attributes are set" do
@@ -4,7 +4,6 @@ describe Saxy::Parser do
4
4
  include FixturesHelper
5
5
 
6
6
  let(:parser) { Saxy::Parser.new(fixture_file("webstore.xml"), "product") }
7
- let(:invalid_parser) { Saxy::Parser.new(fixture_file("invalid.xml"), "product") }
8
7
  let(:file_io) { File.new(fixture_file("webstore.xml")) }
9
8
  let(:io_like) { IOLike.new(file_io) }
10
9
 
@@ -165,12 +164,26 @@ describe Saxy::Parser do
165
164
  end
166
165
  end
167
166
 
168
- it "should raise Saxy::ParsingError on error" do
169
- expect { invalid_parser.each.to_a }.to raise_error { |error|
170
- expect(error).to be_a(Saxy::ParsingError)
171
- expect(error.message).to match(/Opening and ending tag mismatch/)
172
- expect(error.context).to be_a(Nokogiri::XML::SAX::ParserContext)
173
- }
167
+ context "when error handler is not set" do
168
+ let(:parser) { Saxy::Parser.new(fixture_file("invalid.xml"), "product") }
169
+
170
+ it "should raise Saxy::ParsingError on error" do
171
+ expect { parser.each.to_a }.to raise_error { |error|
172
+ expect(error).to be_a(Saxy::ParsingError)
173
+ expect(error.message).to match(/xmlParseEntityRef: no name/)
174
+ expect(error.context).to be_a(Nokogiri::XML::SAX::ParserContext)
175
+ }
176
+ end
177
+ end
178
+
179
+ context "when error handler is set" do
180
+ let(:handler) { proc { |error| error } }
181
+ let(:parser) { Saxy::Parser.new(fixture_file("invalid.xml"), "product", error_handler: handler) }
182
+
183
+ it "should call error handler passing Saxy::ParsingError instance" do
184
+ expect(handler).to receive(:call).with(Saxy::ParsingError)
185
+ parser.each.to_a
186
+ end
174
187
  end
175
188
 
176
189
  it "should return Enumerator when calling #each without a block" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michał Szajbe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-04 00:00:00.000000000 Z
11
+ date: 2018-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri