sax-machine 1.0.2 → 1.0.3

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: 735fbe7eb7f0a9239d94c61a7c3be193b69aaed0
4
- data.tar.gz: 976dc0eb6189bc6ecfbbb39073ddda7d56b7c025
3
+ metadata.gz: 70bbbc0d3143b8a3470722b16bd6ae18c7f20823
4
+ data.tar.gz: 2175ebaaa36b8d325d5bd2a67296edb8ad6c5b9b
5
5
  SHA512:
6
- metadata.gz: 4519f0fc17c789c689bd10f9ebabfb5633a324861c026c12154bb51c4c40dbe7b1c3259e28f365f7c2bf277e8f5e4a2b21441ffe41a489d00afc5644079b91a8
7
- data.tar.gz: ec7638ca60b7ec8290c9baa08aa2b3854ac988769175d4dfa3230f7154269d6960c3185bd9aac4aadc95c9fc57bc10cd35861069f9a17b8bd89e28654fb15ec6
6
+ metadata.gz: de8580d61bbfc9bba11ea486c2eac3796a74b882c61d9fade5c14073b38f684b80c3d48489e6d9f520e0d77d3c8af34c0538fa5b125de33e2708c6b93a41b8de
7
+ data.tar.gz: 6f642b324f6f39c6662e5112fced199d8bd976d968fd228a530e497a0fd695df5232e25c64a34151a5399b00154de0f97878026c34fe8320f89db8728370d3e2
data/HISTORY.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # HEAD
2
2
 
3
+ # 1.0.3
4
+
5
+ * Remove missed `nokogiri` reference [[#54](https://github.com/pauldix/sax-machine/pull/54)]
6
+ * Add support for `Symbol` data type conversion [[#57](https://github.com/pauldix/sax-machine/pull/57)]
7
+ * Add specs for multiple elements with the same alias [[#53](https://github.com/pauldix/sax-machine/pull/53)]
8
+ * Various code and documentation enhancements
9
+
3
10
  # 1.0.2
4
11
 
5
12
  * Make sure SAXConfig getters do not modify internal vars. Prevent race conditions
data/README.md CHANGED
@@ -137,6 +137,26 @@ class X < ActiveRecord::Base
137
137
  end
138
138
  ```
139
139
 
140
+ Multiple elements can be mapped to the same alias:
141
+
142
+ ```ruby
143
+ class RSSEntry
144
+ include SAXMachine
145
+ # ...
146
+ element :pubDate, as: :published
147
+ element :pubdate, as: :published
148
+ element :"dc:date", as: :published
149
+ element :"dc:Date", as: :published
150
+ element :"dcterms:created", as: :published
151
+ end
152
+ ```
153
+
154
+ If more than one of these elements exists in the source, the value from the *last one* is used. The order of
155
+ the `element` declarations in the code is unimportant. The order they are encountered while parsing the
156
+ document determines the value assigned to the alias.
157
+
158
+ If an element is defined in the source but is blank (e.g., `<pubDate></pubDate>`), it is ignored, and non-empty one is picked.
159
+
140
160
  ## Contributing
141
161
 
142
162
  1. Fork it
@@ -1,23 +1,6 @@
1
1
  module SAXMachine
2
2
  class SAXConfig
3
- class AttributeConfig
4
- attr_reader :name, :setter
5
-
6
- def initialize(name, options)
7
- @name = name.to_s
8
- @as = options[:as]
9
- @setter = "#{@as}="
10
- @required = options[:required]
11
- end
12
-
13
- def column
14
- @as || @name.to_sym
15
- end
16
-
17
- def required?
18
- !!@required
19
- end
20
-
3
+ class AttributeConfig < ElementValueConfig
21
4
  def value_from_attrs(attrs)
22
5
  attrs.fetch(@name, nil)
23
6
  end
@@ -12,6 +12,10 @@ module SAXMachine
12
12
  end
13
13
  end
14
14
 
15
+ def sax_parse(xml_text)
16
+ raise NotImplementedError
17
+ end
18
+
15
19
  def _initialize(object, on_error = nil, on_warning = nil)
16
20
  @stack = [ StackNode.new(object) ]
17
21
  @parsed_configs = {}
@@ -60,6 +64,7 @@ module SAXMachine
60
64
  case element_config.data_class.to_s
61
65
  when "Integer" then 0
62
66
  when "Float" then 0.0
67
+ when "Symbol" then nil
63
68
  when "Time" then Time.at(0)
64
69
  when "" then object
65
70
  else
@@ -107,6 +112,12 @@ module SAXMachine
107
112
  when "String" then value != NO_BUFFER ? value.to_s : value
108
113
  when "Integer" then value != NO_BUFFER ? value.to_i : value
109
114
  when "Float" then value != NO_BUFFER ? value.to_f : value
115
+ when "Symbol" then
116
+ if value != NO_BUFFER
117
+ value.to_s.empty? ? nil : value.to_s.downcase.to_sym
118
+ else
119
+ value
120
+ end
110
121
  # Assumes that time elements will be string-based and are not
111
122
  # something else, e.g. seconds since epoch
112
123
  when "Time" then value != NO_BUFFER ? Time.parse(value.to_s) : value
@@ -5,6 +5,13 @@ module SAXMachine
5
5
  class SAXNokogiriHandler < Nokogiri::XML::SAX::Document
6
6
  include SAXAbstractHandler
7
7
 
8
+ def sax_parse(xml_text)
9
+ parser = Nokogiri::XML::SAX::Parser.new(self)
10
+ parser.parse(xml_text) do |ctx|
11
+ ctx.replace_entities = true
12
+ end
13
+ end
14
+
8
15
  alias_method :initialize, :_initialize
9
16
  alias_method :characters, :_characters
10
17
  alias_method :cdata_block, :_characters
@@ -10,6 +10,14 @@ module SAXMachine
10
10
  _reset_element
11
11
  end
12
12
 
13
+ def sax_parse(xml_text)
14
+ Ox.sax_parse(self, StringIO.new(xml_text),
15
+ symbolize: false,
16
+ convert_special: true,
17
+ skip: :skip_return,
18
+ )
19
+ end
20
+
13
21
  def attr(name, str)
14
22
  @attrs[name] = str
15
23
  end
@@ -1,5 +1,5 @@
1
- require "sax-machine/config/sax_attribute"
2
1
  require "sax-machine/config/sax_element_value"
2
+ require "sax-machine/config/sax_attribute"
3
3
  require "sax-machine/config/sax_element"
4
4
  require "sax-machine/config/sax_collection"
5
5
  require "sax-machine/config/sax_ancestor"
@@ -1,5 +1,3 @@
1
- require "nokogiri"
2
-
3
1
  module SAXMachine
4
2
  def self.included(base)
5
3
  base.send(:include, InstanceMethods)
@@ -7,23 +5,10 @@ module SAXMachine
7
5
  end
8
6
 
9
7
  def parse(xml_text, on_error = nil, on_warning = nil)
10
- if SAXMachine.handler == :ox
11
- Ox.sax_parse(
12
- SAXOxHandler.new(self, on_error, on_warning),
13
- StringIO.new(xml_text),
14
- {
15
- symbolize: false,
16
- convert_special: true,
17
- skip: :skip_return,
18
- }
19
- )
20
- else
21
- handler = SAXNokogiriHandler.new(self, on_error, on_warning)
22
- parser = Nokogiri::XML::SAX::Parser.new(handler)
23
- parser.parse(xml_text) do |ctx|
24
- ctx.replace_entities = true
25
- end
26
- end
8
+ handler_klass = SAXMachine.const_get("SAX#{SAXMachine.handler.capitalize}Handler")
9
+
10
+ handler = handler_klass.new(self, on_error, on_warning)
11
+ handler.sax_parse(xml_text)
27
12
 
28
13
  self
29
14
  end
@@ -1,3 +1,3 @@
1
1
  module SAXMachine
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.3"
3
3
  end
@@ -182,6 +182,16 @@ describe "SAXMachine" do
182
182
  document = @klass.parse("<time>1994-02-04T06:20:00Z</time>")
183
183
  expect(document.time).to eq(Time.utc(1994, 2, 4, 6, 20, 0, 0))
184
184
  end
185
+
186
+ it "handles a Symbol class" do
187
+ @klass = Class.new do
188
+ include SAXMachine
189
+ element :symbol, class: Symbol
190
+ end
191
+
192
+ document = @klass.parse("<symbol>MY_SYMBOL_VALUE</symbol>")
193
+ expect(document.symbol).to eq(:my_symbol_value)
194
+ end
185
195
  end
186
196
 
187
197
  describe "the default attribute" do
@@ -914,6 +924,58 @@ describe "SAXMachine" do
914
924
  end
915
925
  end
916
926
 
927
+ describe "with multiple elements with the same alias" do
928
+ let(:item) { ItemElement5.parse(xml) }
929
+
930
+ before do
931
+ class ItemElement5
932
+ include SAXMachine
933
+ element :pubDate, as: :published
934
+ element :"dc:date", as: :published
935
+ end
936
+ end
937
+
938
+ describe "only first defined" do
939
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><pubDate>first value</pubDate></item>" }
940
+
941
+ it "has first value" do
942
+ expect(item.published).to eq("first value")
943
+ end
944
+ end
945
+
946
+ describe "only last defined" do
947
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><dc:date>last value</dc:date></item>" }
948
+
949
+ it "has last value" do
950
+ expect(item.published).to eq("last value")
951
+ end
952
+ end
953
+
954
+ describe "both defined" do
955
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><pubDate>first value</pubDate><dc:date>last value</dc:date></item>" }
956
+
957
+ it "has last value" do
958
+ expect(item.published).to eq("last value")
959
+ end
960
+ end
961
+
962
+ describe "both defined but order is reversed" do
963
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><dc:date>last value</dc:date><pubDate>first value</pubDate></item>" }
964
+
965
+ it "has first value" do
966
+ expect(item.published).to eq("first value")
967
+ end
968
+ end
969
+
970
+ describe "both defined but last is empty" do
971
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><pubDate>first value</pubDate><dc:date></dc:date></item>" }
972
+
973
+ it "has first value" do
974
+ expect(item.published).to eq("first value")
975
+ end
976
+ end
977
+ end
978
+
917
979
  describe "with error handling" do
918
980
  before do
919
981
  @xml = %[
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sax-machine
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Dix
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-09-25 00:00:00.000000000 Z
14
+ date: 2014-11-06 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rspec