nori 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nori might be problematic. Click here for more details.

@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ doc
3
+ coverage
4
+ *~
5
+ *.gem
6
+ .bundle
7
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,8 @@
1
+ script: "rake"
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - ree
6
+ - rbx
7
+ - jruby
8
+
@@ -0,0 +1,36 @@
1
+ == 0.2.0 (2011-04-30)
2
+
3
+ * Removed JSON from the original Crack basis
4
+ * Fixed a problem with Object#blank?
5
+ * Added swappable parsers
6
+ * Added a Nokogiri parser with you can switch to via:
7
+
8
+ Nori.parser = :nokogiri
9
+
10
+ == 0.1.7 2010-02-19
11
+ * 1 minor patch
12
+ * Added patch from @purp for ISO 8601 date/time format
13
+
14
+ == 0.1.6 2010-01-31
15
+ * 1 minor patch
16
+ * Added Crack::VERSION constant - http://weblog.rubyonrails.org/2009/9/1/gem-packaging-best-practices
17
+
18
+ == 0.1.5 2010-01-27
19
+ * 1 minor patch
20
+ * Strings that begin with dates shouldn't be parsed as such (sandro)
21
+
22
+ == 0.1.3 2009-06-22
23
+ * 1 minor patch
24
+ * Parsing a text node with attributes stores them in the attributes method (tamalw)
25
+
26
+ == 0.1.2 2009-04-21
27
+ * 2 minor patches
28
+ * Correct unnormalization of attribute values (der-flo)
29
+ * Fix error in parsing YAML in the case where a hash value ends with backslashes, and there are subsequent values in the hash (deadprogrammer)
30
+
31
+ == 0.1.1 2009-03-31
32
+ * 1 minor patch
33
+ * Parsing empty or blank xml now returns empty hash instead of raising error.
34
+
35
+ == 0.1.0 2009-03-28
36
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in nori.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Daniel Harrington
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ Nori ![http://travis-ci.org/rubiii/nori](http://travis-ci.org/rubiii/nori.png)
2
+ ====
3
+
4
+ Really simple XML parsing ripped from Crack which ripped it from Merb.
5
+ Nori was created to bypass the stale development of Crack, improve its XML parser
6
+ and fix certain issues.
7
+
8
+ ``` ruby
9
+ Nori.parse("<tag>This is the contents</tag>")
10
+ # => { 'tag' => 'This is the contents' }
11
+ ```
12
+
13
+ Nori supports pluggable parsers and ships with both REXML and Nokogiri implementations.
14
+ It defaults to REXML, but you can change it to use Nokogiri via:
15
+
16
+ ``` ruby
17
+ Nori.parser = :nokogiri
18
+ ```
19
+
20
+ Make sure Nokogiri is in your LOAD_PATH when parsing XML, because Nori tries to load it
21
+ when it's needed.
@@ -0,0 +1,16 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rspec/core/rake_task"
5
+
6
+ desc "Benchmark Nori parsers"
7
+ task :benchmark do
8
+ require "benchmark/benchmark"
9
+ end
10
+
11
+ RSpec::Core::RakeTask.new do |t|
12
+ t.rspec_opts = %w(-fd -c)
13
+ end
14
+
15
+ task :default => :spec
16
+ task :test => :spec
@@ -0,0 +1,19 @@
1
+ $:.push File.expand_path("../../lib", __FILE__)
2
+ require "nori"
3
+
4
+ require "benchmark"
5
+
6
+ Benchmark.bm 30 do |x|
7
+
8
+ num = 250
9
+ xml = File.read File.expand_path("../soap_response.xml", __FILE__)
10
+
11
+ x.report "rexml parser" do
12
+ num.times { Nori.parse xml, :rexml }
13
+ end
14
+
15
+ x.report "nokogiri parser" do
16
+ num.times { Nori.parse xml, :nokogiri }
17
+ end
18
+
19
+ end
@@ -0,0 +1,266 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3
+ <soap:Body>
4
+ <GetICB_9_2_4_DestInfoWithDestIdResponse xmlns="http://airline.com/">
5
+ <GetICB_9_2_4_DestInfoWithDestIdResult>
6
+ <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
7
+ <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="CL_9_2_4_DestInfo" msdata:UseCurrentLocale="true">
8
+ <xs:complexType>
9
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
10
+ <xs:element name="CL_9_2_4_DestInfo">
11
+ <xs:complexType>
12
+ <xs:sequence>
13
+ <xs:element name="DESTINATION" minOccurs="0">
14
+ <xs:simpleType>
15
+ <xs:restriction base="xs:string">
16
+ <xs:maxLength value="64" />
17
+ </xs:restriction>
18
+ </xs:simpleType>
19
+ </xs:element>
20
+ <xs:element name="COUNTRY" minOccurs="0">
21
+ <xs:simpleType>
22
+ <xs:restriction base="xs:string">
23
+ <xs:maxLength value="50" />
24
+ </xs:restriction>
25
+ </xs:simpleType>
26
+ </xs:element>
27
+ <xs:element name="AIRPORTNAME" minOccurs="0">
28
+ <xs:simpleType>
29
+ <xs:restriction base="xs:string">
30
+ <xs:maxLength value="70" />
31
+ </xs:restriction>
32
+ </xs:simpleType>
33
+ </xs:element>
34
+ <xs:element name="DISTANCE_APT_CTY" minOccurs="0">
35
+ <xs:simpleType>
36
+ <xs:restriction base="xs:string">
37
+ <xs:maxLength value="50" />
38
+ </xs:restriction>
39
+ </xs:simpleType>
40
+ </xs:element>
41
+ <xs:element name="TRANSPORT_APT_CTY" minOccurs="0">
42
+ <xs:simpleType>
43
+ <xs:restriction base="xs:string">
44
+ <xs:maxLength value="50" />
45
+ </xs:restriction>
46
+ </xs:simpleType>
47
+ </xs:element>
48
+ <xs:element name="REVCABIN" minOccurs="0">
49
+ <xs:simpleType>
50
+ <xs:restriction base="xs:string">
51
+ <xs:maxLength value="50" />
52
+ </xs:restriction>
53
+ </xs:simpleType>
54
+ </xs:element>
55
+ <xs:element name="REVCOCKPIT" minOccurs="0">
56
+ <xs:simpleType>
57
+ <xs:restriction base="xs:string">
58
+ <xs:maxLength value="50" />
59
+ </xs:restriction>
60
+ </xs:simpleType>
61
+ </xs:element>
62
+ <xs:element name="GROUPTEXT" minOccurs="0">
63
+ <xs:simpleType>
64
+ <xs:restriction base="xs:string">
65
+ <xs:maxLength value="50" />
66
+ </xs:restriction>
67
+ </xs:simpleType>
68
+ </xs:element>
69
+ <xs:element name="SORT" type="xs:decimal" minOccurs="0" />
70
+ <xs:element name="HEADING" minOccurs="0">
71
+ <xs:simpleType>
72
+ <xs:restriction base="xs:string">
73
+ <xs:maxLength value="30" />
74
+ </xs:restriction>
75
+ </xs:simpleType>
76
+ </xs:element>
77
+ <xs:element name="VISIBLE" type="xs:decimal" minOccurs="0" />
78
+ <xs:element name="SORT1" type="xs:decimal" minOccurs="0" />
79
+ <xs:element name="ITEMSORT" type="xs:decimal" minOccurs="0" />
80
+ <xs:element name="AUSWAHLTEXT" minOccurs="0">
81
+ <xs:simpleType>
82
+ <xs:restriction base="xs:string">
83
+ <xs:maxLength value="255" />
84
+ </xs:restriction>
85
+ </xs:simpleType>
86
+ </xs:element>
87
+ <xs:element name="REVDATE" type="xs:dateTime" minOccurs="0" />
88
+ <xs:element name="CABIN" type="xs:decimal" minOccurs="0" />
89
+ <xs:element name="COCKPIT" type="xs:decimal" minOccurs="0" />
90
+ <xs:element name="APIATA" minOccurs="0">
91
+ <xs:simpleType>
92
+ <xs:restriction base="xs:string">
93
+ <xs:maxLength value="3" />
94
+ </xs:restriction>
95
+ </xs:simpleType>
96
+ </xs:element>
97
+ </xs:sequence>
98
+ </xs:complexType>
99
+ </xs:element>
100
+ </xs:choice>
101
+ </xs:complexType>
102
+ </xs:element>
103
+ </xs:schema>
104
+ <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
105
+ <DocumentElement xmlns="">
106
+ <CL_9_2_4_DestInfo diffgr:id="CL_9_2_4_DestInfo1" msdata:rowOrder="0">
107
+ <DESTINATION>PALMA DE MALLORCA</DESTINATION>
108
+ <COUNTRY>Spain Schengen</COUNTRY>
109
+ <AIRPORTNAME>Son San Juan</AIRPORTNAME>
110
+ <DISTANCE_APT_CTY>11 km</DISTANCE_APT_CTY>
111
+ <REVCABIN>08.02.10</REVCABIN>
112
+ <REVCOCKPIT>08.02.10</REVCOCKPIT>
113
+ <GROUPTEXT>Passengers</GROUPTEXT>
114
+ <SORT>1</SORT>
115
+ <HEADING>Disembarking:</HEADING>
116
+ <VISIBLE>-1</VISIBLE>
117
+ <SORT1>2</SORT1>
118
+ <ITEMSORT>0</ITEMSORT>
119
+ <AUSWAHLTEXT>Baby buggies are delivered at aircraft door or stairs.</AUSWAHLTEXT>
120
+ <REVDATE>2008-09-01T00:00:00+02:00</REVDATE>
121
+ <CABIN>-1</CABIN>
122
+ <COCKPIT>0</COCKPIT>
123
+ <APIATA>PMI</APIATA>
124
+ </CL_9_2_4_DestInfo>
125
+ <CL_9_2_4_DestInfo diffgr:id="CL_9_2_4_DestInfo2" msdata:rowOrder="1">
126
+ <DESTINATION>PALMA DE MALLORCA</DESTINATION>
127
+ <COUNTRY>Spain Schengen</COUNTRY>
128
+ <AIRPORTNAME>Son San Juan</AIRPORTNAME>
129
+ <DISTANCE_APT_CTY>11 km</DISTANCE_APT_CTY>
130
+ <REVCABIN>08.02.10</REVCABIN>
131
+ <REVCOCKPIT>08.02.10</REVCOCKPIT>
132
+ <GROUPTEXT>Aircraft</GROUPTEXT>
133
+ <SORT>2</SORT>
134
+ <HEADING>Turnaround:</HEADING>
135
+ <VISIBLE>-1</VISIBLE>
136
+ <SORT1>5.30</SORT1>
137
+ <ITEMSORT>0</ITEMSORT>
138
+ <AUSWAHLTEXT>Station applies EST process.</AUSWAHLTEXT>
139
+ <REVDATE>2009-05-05T00:00:00+02:00</REVDATE>
140
+ <CABIN>-1</CABIN>
141
+ <COCKPIT>-1</COCKPIT>
142
+ <APIATA>PMI</APIATA>
143
+ </CL_9_2_4_DestInfo>
144
+ <CL_9_2_4_DestInfo diffgr:id="CL_9_2_4_DestInfo3" msdata:rowOrder="2">
145
+ <DESTINATION>PALMA DE MALLORCA</DESTINATION>
146
+ <COUNTRY>Spain Schengen</COUNTRY>
147
+ <AIRPORTNAME>Son San Juan</AIRPORTNAME>
148
+ <DISTANCE_APT_CTY>11 km</DISTANCE_APT_CTY>
149
+ <REVCABIN>08.02.10</REVCABIN>
150
+ <REVCOCKPIT>08.02.10</REVCOCKPIT>
151
+ <GROUPTEXT>General</GROUPTEXT>
152
+ <SORT>4</SORT>
153
+ <HEADING>Addresses:</HEADING>
154
+ <VISIBLE>-1</VISIBLE>
155
+ <SORT1>8.50</SORT1>
156
+ <ITEMSORT>1</ITEMSORT>
157
+ <AUSWAHLTEXT>
158
+ Station Manager:
159
+ YYYYYYYY XXXXXXX
160
+ PMIKXXX
161
+ Tel.:+34 971 xxx xxx
162
+ Mobile:+ 34 600 46 xx xx
163
+ </AUSWAHLTEXT>
164
+ <REVDATE>2010-02-08T00:00:00+01:00</REVDATE>
165
+ <CABIN>-1</CABIN>
166
+ <COCKPIT>-1</COCKPIT>
167
+ <APIATA>PMI</APIATA>
168
+ </CL_9_2_4_DestInfo>
169
+ <CL_9_2_4_DestInfo diffgr:id="CL_9_2_4_DestInfo4" msdata:rowOrder="3">
170
+ <DESTINATION>PALMA DE MALLORCA</DESTINATION>
171
+ <COUNTRY>Spain Schengen</COUNTRY>
172
+ <AIRPORTNAME>Son San Juan</AIRPORTNAME>
173
+ <DISTANCE_APT_CTY>11 km</DISTANCE_APT_CTY>
174
+ <REVCABIN>08.02.10</REVCABIN>
175
+ <REVCOCKPIT>08.02.10</REVCOCKPIT>
176
+ <GROUPTEXT>General</GROUPTEXT>
177
+ <SORT>4</SORT>
178
+ <HEADING>Addresses:</HEADING>
179
+ <VISIBLE>-1</VISIBLE>
180
+ <SORT1>8.50</SORT1>
181
+ <ITEMSORT>2</ITEMSORT>
182
+ <AUSWAHLTEXT>
183
+ Handling Agent:
184
+ xxxxxxx Airport Services
185
+ Operations
186
+ PMIIxxx
187
+ Tel +34 971 xxx xxx
188
+ Passenger Services
189
+ PMIPXXX
190
+ Tel : +34 971 xxx xxx
191
+ </AUSWAHLTEXT>
192
+ <REVDATE>2010-02-08T00:00:00+01:00</REVDATE>
193
+ <CABIN>-1</CABIN>
194
+ <COCKPIT>-1</COCKPIT>
195
+ <APIATA>PMI</APIATA>
196
+ </CL_9_2_4_DestInfo>
197
+ <CL_9_2_4_DestInfo diffgr:id="CL_9_2_4_DestInfo5" msdata:rowOrder="4">
198
+ <DESTINATION>PALMA DE MALLORCA</DESTINATION>
199
+ <COUNTRY>Spain Schengen</COUNTRY>
200
+ <AIRPORTNAME>Son San Juan</AIRPORTNAME>
201
+ <DISTANCE_APT_CTY>11 km</DISTANCE_APT_CTY>
202
+ <REVCABIN>08.02.10</REVCABIN>
203
+ <REVCOCKPIT>08.02.10</REVCOCKPIT>
204
+ <GROUPTEXT>General</GROUPTEXT>
205
+ <SORT>4</SORT>
206
+ <HEADING>Announcements:</HEADING>
207
+ <VISIBLE>-1</VISIBLE>
208
+ <SORT1>11</SORT1>
209
+ <ITEMSORT>1</ITEMSORT>
210
+ <AUSWAHLTEXT>Prerecorded Spanish announcements available.</AUSWAHLTEXT>
211
+ <REVDATE>2009-12-30T00:00:00+01:00</REVDATE>
212
+ <CABIN>-1</CABIN>
213
+ <COCKPIT>0</COCKPIT>
214
+ <APIATA>PMI</APIATA>
215
+ </CL_9_2_4_DestInfo>
216
+ <CL_9_2_4_DestInfo diffgr:id="CL_9_2_4_DestInfo6" msdata:rowOrder="5">
217
+ <DESTINATION>PALMA DE MALLORCA</DESTINATION>
218
+ <COUNTRY>Spain Schengen</COUNTRY>
219
+ <AIRPORTNAME>Son San Juan</AIRPORTNAME>
220
+ <DISTANCE_APT_CTY>11 km</DISTANCE_APT_CTY>
221
+ <REVCABIN>08.02.10</REVCABIN>
222
+ <REVCOCKPIT>08.02.10</REVCOCKPIT>
223
+ <GROUPTEXT>General</GROUPTEXT>
224
+ <SORT>4</SORT>
225
+ <HEADING>Life jackets / DEMO:</HEADING>
226
+ <VISIBLE>-1</VISIBLE>
227
+ <SORT1>12</SORT1>
228
+ <ITEMSORT>0</ITEMSORT>
229
+ <AUSWAHLTEXT>
230
+ Infant life jackets to be distributed.
231
+ DEMO with life jackets.
232
+ </AUSWAHLTEXT>
233
+ <REVDATE>2002-07-24T00:00:00+02:00</REVDATE>
234
+ <CABIN>-1</CABIN>
235
+ <COCKPIT>0</COCKPIT>
236
+ <APIATA>PMI</APIATA>
237
+ </CL_9_2_4_DestInfo>
238
+ <CL_9_2_4_DestInfo diffgr:id="CL_9_2_4_DestInfo7" msdata:rowOrder="6">
239
+ <DESTINATION>PALMA DE MALLORCA</DESTINATION>
240
+ <COUNTRY>Spain Schengen</COUNTRY>
241
+ <AIRPORTNAME>Son San Juan</AIRPORTNAME>
242
+ <DISTANCE_APT_CTY>11 km</DISTANCE_APT_CTY>
243
+ <REVCABIN>08.02.10</REVCABIN>
244
+ <REVCOCKPIT>08.02.10</REVCOCKPIT>
245
+ <GROUPTEXT>Catering</GROUPTEXT>
246
+ <SORT>5</SORT>
247
+ <HEADING>General:</HEADING>
248
+ <VISIBLE>0</VISIBLE>
249
+ <SORT1>1</SORT1>
250
+ <ITEMSORT>1</ITEMSORT>
251
+ <AUSWAHLTEXT>
252
+ LSG XXX XXXX
253
+ Tel.: +34 971 xxx xxx or xxx xxx
254
+ Sita: PMIAXXX
255
+ </AUSWAHLTEXT>
256
+ <REVDATE>2005-06-01T00:00:00+02:00</REVDATE>
257
+ <CABIN>-1</CABIN>
258
+ <COCKPIT>0</COCKPIT>
259
+ <APIATA>PMI</APIATA>
260
+ </CL_9_2_4_DestInfo>
261
+ </DocumentElement>
262
+ </diffgr:diffgram>
263
+ </GetICB_9_2_4_DestInfoWithDestIdResult>
264
+ </GetICB_9_2_4_DestInfoWithDestIdResponse>
265
+ </soap:Body>
266
+ </soap:Envelope>
@@ -0,0 +1,18 @@
1
+ require "nori/version"
2
+ require "nori/core_ext"
3
+ require "nori/parser"
4
+
5
+ module Nori
6
+
7
+ # Translates the given +xml+ to a Hash. Accepts an optional +parser+ to use.
8
+ def self.parse(xml, parser = nil)
9
+ return {} if xml.blank?
10
+ Parser.parse xml, parser
11
+ end
12
+
13
+ # Sets the +parser+ to use.
14
+ def self.parser=(parser)
15
+ Parser.use = parser
16
+ end
17
+
18
+ end
@@ -0,0 +1,3 @@
1
+ require "nori/core_ext/object"
2
+ require "nori/core_ext/string"
3
+ require "nori/core_ext/hash"
@@ -0,0 +1,70 @@
1
+ require "uri"
2
+
3
+ module Nori
4
+ module CoreExt
5
+ module Hash
6
+
7
+ # @return <String> This hash as a query string
8
+ #
9
+ # @example
10
+ # { :name => "Bob",
11
+ # :address => {
12
+ # :street => '111 Ruby Ave.',
13
+ # :city => 'Ruby Central',
14
+ # :phones => ['111-111-1111', '222-222-2222']
15
+ # }
16
+ # }.to_params
17
+ # #=> "name=Bob&address[city]=Ruby Central&address[phones][]=111-111-1111&address[phones][]=222-222-2222&address[street]=111 Ruby Ave."
18
+ def to_params
19
+ params = self.map { |k, v| normalize_param(k,v) }.join
20
+ params.chop! # trailing &
21
+ params
22
+ end
23
+
24
+ # @param key<Object> The key for the param.
25
+ # @param value<Object> The value for the param.
26
+ #
27
+ # @return <String> This key value pair as a param
28
+ #
29
+ # @example normalize_param(:name, "Bob Jones") #=> "name=Bob%20Jones&"
30
+ def normalize_param(key, value)
31
+ param = ''
32
+ stack = []
33
+
34
+ if value.is_a?(Array)
35
+ param << value.map { |element| normalize_param("#{key}[]", element) }.join
36
+ elsif value.is_a?(Hash)
37
+ stack << [key,value]
38
+ else
39
+ param << "#{key}=#{URI.encode(value.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}&"
40
+ end
41
+
42
+ stack.each do |parent, hash|
43
+ hash.each do |key, value|
44
+ if value.is_a?(Hash)
45
+ stack << ["#{parent}[#{key}]", value]
46
+ else
47
+ param << normalize_param("#{parent}[#{key}]", value)
48
+ end
49
+ end
50
+ end
51
+
52
+ param
53
+ end
54
+
55
+ # @return <String> The hash as attributes for an XML tag.
56
+ #
57
+ # @example
58
+ # { :one => 1, "two"=>"TWO" }.to_xml_attributes
59
+ # #=> 'one="1" two="TWO"'
60
+ def to_xml_attributes
61
+ map do |k, v|
62
+ %{#{k.to_s.snake_case.sub(/^(.{1,1})/) { |m| m.downcase }}="#{v}"}
63
+ end.join(' ')
64
+ end
65
+
66
+ end
67
+ end
68
+ end
69
+
70
+ Hash.send :include, Nori::CoreExt::Hash