saxy 0.7.0 → 0.7.1

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.
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