csvlint 0.2.6 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YjRlMTk0ZmM3ZjY0YmExNWY2YzgxNTFiNmYyMDc3OTdiMmIyOWQ2Ng==
4
+ MTJlZWM1ZDA0ZDMzMjBkM2I1OGUxYjM1NTIxZTA1NWVkODJlMDFiYQ==
5
5
  data.tar.gz: !binary |-
6
- NWJkYzE4YTY4ODZjMWY3M2M5MDNkMjhhMjFhMmMyOGYyNTBmY2ZlZQ==
6
+ MWE1MWYzZjk3YjgwMTJhNzBjZGM4NTMyOGYzYTU1ZWM4ZDc4NTI2YQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NjM1ZGJhNGU0ODE0NjY0YjQ3ZjU0ZjRjMmRkYmI1YjZmODQzZWM3YjUyYzMw
10
- Y2U2MWM2YzY0NWU3NTVmYzJiOWNlZWVhZGY1ZjQyOWUzNWU3MWU5MDU0MDA2
11
- MWM5MDM5ZmRkYTY3YzYxYWYzOGFmMGE1YzEzODFmMmM5MTdkZjQ=
9
+ MWU5NTAxZDVjMGI3YTNiYTBlNTJmODkxNTBkYzdiN2ExN2E3NGE2ZjI5M2Nl
10
+ ZGY0OWM3ZTVjODNiNjcyZDMwODhhNTc3ODIyZGMyMzUzYWE2ZTMyZmFmNGIw
11
+ NDFiYzc5YzNlNTFlODQ1ODE1YzZkMDU0MDdkMzE3MmVlNWUyYmU=
12
12
  data.tar.gz: !binary |-
13
- NTc1NjQzZTM2M2FlYjZkYWQzNzljMmU1OTI3YTViMDc4MTc0ZWJiZjcxMzAy
14
- MzhiNWFmNzg4MGQ5NzAxNzQ5NTRiNjAyNzU4YjMzN2Q4ZjlmNmZmZWVlYTEy
15
- ZDhhOThjM2Y0MmYxMDJiYTk5NmQ3MzEwN2JlMTVjMjk4ZmVkYmM=
13
+ MjBhYTU1ZWMzNjcxMmU1NjU1ZjZkYTE5M2YwOTQ5NzYyOWYzNmM2NzkxNWJk
14
+ Y2VlM2JkMmRlYmNhNzM5MGI0ZDg2YWQzOTNhYzg1YjAyNDRiNTFiNmRlZjk4
15
+ Nzc0YjJlOWM0MGVmMjAzZTBiZjQwZTc4MTU5YTVjMGFiZDFjNmQ=
@@ -1,2 +1,2 @@
1
- # Don't fuck with my CSV files
1
+ # Don't mess with my CSV files
2
2
  *.csv binary
data/.gitignore CHANGED
@@ -25,4 +25,4 @@ features/fixtures/csvw
25
25
 
26
26
  bin/run-csvw-tests
27
27
 
28
- features/csvw_json_transformation_tests.feature
28
+ csvlint-earl.ttl
@@ -42,5 +42,7 @@ Gem::Specification.new do |spec|
42
42
  spec.add_development_dependency "pry"
43
43
  spec.add_development_dependency "github_changelog_generator"
44
44
  spec.add_development_dependency "aruba"
45
+ spec.add_development_dependency "rdf"
46
+ spec.add_development_dependency "rdf-turtle"
45
47
 
46
48
  end
@@ -0,0 +1,4 @@
1
+ {+url}-metadata.json
2
+ csv-metadata.json
3
+ {+url}.json
4
+ csvm.json
@@ -47,7 +47,7 @@ When(/^I carry out CSVW validation$/) do
47
47
  end
48
48
 
49
49
  Then(/^there should be errors$/) do
50
- # this test is only used for CSVW testing; :invalid_encoding masks lack of real errors
50
+ # this test is only used for CSVW testing; :invalid_encoding & :line_breaks mask lack of real errors
51
51
  @errors.delete_if { |e| e.instance_of?(Csvlint::ErrorMessage) && [:invalid_encoding, :line_breaks].include?(e.type) }
52
52
  expect( @errors.count ).to be > 0
53
53
  end
@@ -0,0 +1,66 @@
1
+ require 'rdf'
2
+ require 'rdf/turtle'
3
+
4
+ class EarlFormatter
5
+ def initialize(step_mother, io, options)
6
+ output = RDF::Resource.new("")
7
+ @graph = RDF::Graph.new
8
+ @graph << [ CSVLINT, RDF.type, RDF::DOAP.Project ]
9
+ @graph << [ CSVLINT, RDF.type, EARL.TestSubject ]
10
+ @graph << [ CSVLINT, RDF.type, EARL.Software ]
11
+ @graph << [ CSVLINT, RDF::DOAP.name, "csvlint" ]
12
+ @graph << [ CSVLINT, RDF::DC.title, "csvlint" ]
13
+ @graph << [ CSVLINT, RDF::DOAP.description, "CSV validator" ]
14
+ @graph << [ CSVLINT, RDF::DOAP.homepage, RDF::Resource.new("https://github.com/theodi/csvlint.rb") ]
15
+ @graph << [ CSVLINT, RDF::DOAP.license, RDF::Resource.new("https://raw.githubusercontent.com/theodi/csvlint.rb/master/LICENSE.md") ]
16
+ @graph << [ CSVLINT, RDF::DOAP["programming-language"], "Ruby" ]
17
+ @graph << [ CSVLINT, RDF::DOAP.implements, RDF::Resource.new("http://www.w3.org/TR/tabular-data-model/") ]
18
+ @graph << [ CSVLINT, RDF::DOAP.implements, RDF::Resource.new("http://www.w3.org/TR/tabular-metadata/") ]
19
+ @graph << [ CSVLINT, RDF::DOAP.developer, ODI ]
20
+ @graph << [ CSVLINT, RDF::DOAP.maintainer, ODI ]
21
+ @graph << [ CSVLINT, RDF::DOAP.documenter, ODI ]
22
+ @graph << [ CSVLINT, RDF::FOAF.maker, ODI ]
23
+ @graph << [ CSVLINT, RDF::DC.creator, ODI ]
24
+ @graph << [ output, RDF::FOAF["primaryTopic"], CSVLINT ]
25
+ @graph << [ output, RDF::DC.issued, DateTime.now ]
26
+ @graph << [ output, RDF::FOAF.maker, ODI ]
27
+ @graph << [ ODI, RDF.type, RDF::FOAF.Organization ]
28
+ @graph << [ ODI, RDF.type, EARL.Assertor ]
29
+ @graph << [ ODI, RDF::FOAF.name, "Open Data Institute" ]
30
+ @graph << [ ODI, RDF::FOAF.homepage, "https://theodi.org/" ]
31
+ end
32
+
33
+ def scenario_name(keyword, name, file_colon_line, source_indent)
34
+ @test = RDF::Resource.new("http://www.w3.org/2013/csvw/tests/#{name.split(" ")[0]}")
35
+ end
36
+
37
+ def after_steps(steps)
38
+ passed = true
39
+ steps.each do |s|
40
+ passed = false unless s.status == :passed
41
+ end
42
+ a = RDF::Node.new
43
+ @graph << [ a, RDF.type, EARL.Assertion ]
44
+ @graph << [ a, EARL.assertedBy, ODI ]
45
+ @graph << [ a, EARL.subject, CSVLINT ]
46
+ @graph << [ a, EARL.test, @test ]
47
+ @graph << [ a, EARL.mode, EARL.automatic ]
48
+ r = RDF::Node.new
49
+ @graph << [ a, EARL.result, r ]
50
+ @graph << [ r, RDF.type, EARL.TestResult ]
51
+ @graph << [ r, EARL.outcome, passed ? EARL.passed : EARL.failed ]
52
+ @graph << [ r, RDF::DC.date, DateTime.now ]
53
+ end
54
+
55
+ def after_features(features)
56
+ RDF::Writer.for(:ttl).open("csvlint-earl.ttl", { :prefixes => { "earl" => EARL }, :standard_prefixes => true, :canonicalize => true, :literal_shorthand => true }) do |writer|
57
+ writer << @graph
58
+ end
59
+ end
60
+
61
+ private
62
+ EARL = RDF::Vocabulary.new("http://www.w3.org/ns/earl#")
63
+ ODI = RDF::Resource.new("https://theodi.org/")
64
+ CSVLINT = RDF::Resource.new("https://github.com/theodi/csvlint.rb")
65
+
66
+ end
@@ -2,9 +2,10 @@ require 'json'
2
2
  require 'open-uri'
3
3
  require 'uri'
4
4
 
5
- BASE_URI = "http://w3c.github.io/csvw/tests/"
5
+ BASE_URI = "http://www.w3.org/2013/csvw/tests/"
6
6
  BASE_PATH = File.join(File.dirname(__FILE__), "..", "fixtures", "csvw")
7
- FEATURE_FILE_PATH = File.join(File.dirname(__FILE__), "..", "csvw_validation_tests.feature")
7
+ FEATURE_BASE_PATH = File.join(File.dirname(__FILE__), "..")
8
+ VALIDATION_FEATURE_FILE_PATH = File.join(FEATURE_BASE_PATH, "csvw_validation_tests.feature")
8
9
  SCRIPT_FILE_PATH = File.join(File.dirname(__FILE__), "..", "..", "bin", "run-csvw-tests")
9
10
 
10
11
  Dir.mkdir(BASE_PATH) unless Dir.exist?(BASE_PATH)
@@ -30,7 +31,7 @@ end
30
31
 
31
32
  File.open(SCRIPT_FILE_PATH, 'w') do |file|
32
33
  File.chmod(0755, SCRIPT_FILE_PATH)
33
- manifest = JSON.parse( open("http://w3c.github.io/csvw/tests/manifest-validation.jsonld").read )
34
+ manifest = JSON.parse( open("http://www.w3.org/2013/csvw/tests/manifest-validation.jsonld").read )
34
35
  manifest["entries"].each do |entry|
35
36
  type = "valid"
36
37
  case entry["type"]
@@ -52,11 +53,11 @@ File.open(SCRIPT_FILE_PATH, 'w') do |file|
52
53
  end
53
54
  end unless File.exist? SCRIPT_FILE_PATH
54
55
 
55
- File.open(FEATURE_FILE_PATH, 'w') do |file|
56
- file.puts "# Auto-generated file based on standard validation CSVW tests from http://w3c.github.io/csvw/tests/manifest-validation.jsonld"
56
+ File.open(VALIDATION_FEATURE_FILE_PATH, 'w') do |file|
57
+ file.puts "# Auto-generated file based on standard validation CSVW tests from http://www.w3.org/2013/csvw/tests/manifest-validation.jsonld"
57
58
  file.puts ""
58
59
 
59
- manifest = JSON.parse( open("http://w3c.github.io/csvw/tests/manifest-validation.jsonld").read )
60
+ manifest = JSON.parse( open("http://www.w3.org/2013/csvw/tests/manifest-validation.jsonld").read )
60
61
 
61
62
  file.puts "Feature: #{manifest["label"]}"
62
63
  file.puts ""
@@ -83,11 +84,15 @@ File.open(FEATURE_FILE_PATH, 'w') do |file|
83
84
  file.puts "\t\tAnd the metadata is stored at the url \"#{metadata}\""
84
85
  end
85
86
  provided_files << action_uri.to_s
86
- missing_files = [
87
- URI.join(action_uri, '/.well-known/csvm').to_s,
88
- "#{action_uri}-metadata.json",
89
- URI.join(action_uri, 'csv-metadata.json').to_s
90
- ]
87
+ if entry["name"].include?("/.well-known/csvm")
88
+ file.puts "\t\tAnd I have a file called \"w3.org/.well-known/csvm\" at the url \"http://www.w3.org/.well-known/csvm\""
89
+ missing_files << "#{action_uri}.json"
90
+ missing_files << URI.join(action_uri, 'csvm.json').to_s
91
+ else
92
+ missing_files << URI.join(action_uri, '/.well-known/csvm').to_s
93
+ end
94
+ missing_files << "#{action_uri}-metadata.json"
95
+ missing_files << URI.join(action_uri, 'csv-metadata.json').to_s
91
96
  end
92
97
  entry["implicit"].each do |implicit|
93
98
  implicit_uri, implicit_file = cache_file(implicit)
@@ -104,11 +109,11 @@ File.open(FEATURE_FILE_PATH, 'w') do |file|
104
109
  file.puts "\t\tThen there should not be errors"
105
110
  file.puts "\t\tAnd there should be warnings"
106
111
  elsif entry["type"] == "csvt:NegativeValidationTest"
107
- file.puts "\t\tThen there should be errors"
112
+ file.puts "\t\tThen there should be errors"
108
113
  else
109
- file.puts "\t\tThen there should not be errors"
110
- file.puts "\t\tAnd there should not be warnings"
114
+ file.puts "\t\tThen there should not be errors"
115
+ file.puts "\t\tAnd there should not be warnings"
111
116
  end
112
117
  file.puts "\t"
113
118
  end
114
- end unless File.exist? FEATURE_FILE_PATH
119
+ end unless File.exist? VALIDATION_FEATURE_FILE_PATH
@@ -3,9 +3,9 @@ module Csvlint
3
3
  class Column
4
4
  include Csvlint::ErrorCollector
5
5
 
6
- attr_reader :id, :about_url, :datatype, :default, :lang, :name, :null, :number, :ordered, :property_url, :required, :separator, :source_number, :suppress_output, :text_direction, :titles, :value_url, :virtual, :annotations
6
+ attr_reader :id, :about_url, :datatype, :default, :lang, :name, :null, :number, :ordered, :property_url, :required, :separator, :source_number, :suppress_output, :text_direction, :default_name, :titles, :value_url, :virtual, :annotations
7
7
 
8
- def initialize(number, name, id: nil, about_url: nil, datatype: { "@id" => "http://www.w3.org/2001/XMLSchema#string" }, default: "", lang: "und", null: [""], ordered: false, property_url: nil, required: false, separator: nil, source_number: nil, suppress_output: false, text_direction: :inherit, titles: {}, value_url: nil, virtual: false, annotations: [], warnings: [])
8
+ def initialize(number, name, id: nil, about_url: nil, datatype: { "@id" => "http://www.w3.org/2001/XMLSchema#string" }, default: "", lang: "und", null: [""], ordered: false, property_url: nil, required: false, separator: nil, source_number: nil, suppress_output: false, text_direction: :inherit, default_name: nil, titles: {}, value_url: nil, virtual: false, annotations: [], warnings: [])
9
9
  @number = number
10
10
  @name = name
11
11
  @id = id
@@ -21,6 +21,7 @@ module Csvlint
21
21
  @source_number = source_number || number
22
22
  @suppress_output = suppress_output
23
23
  @text_direction = text_direction
24
+ @default_name = default_name
24
25
  @titles = titles
25
26
  @value_url = value_url
26
27
  @virtual = virtual
@@ -58,51 +59,64 @@ module Csvlint
58
59
  datatype: inherited_properties["datatype"] || { "@id" => "http://www.w3.org/2001/XMLSchema#string" },
59
60
  lang: inherited_properties["lang"] || "und",
60
61
  null: inherited_properties["null"] || [""],
61
- property_url: column_desc["propertyUrl"],
62
+ default: inherited_properties["default"] || "",
63
+ about_url: inherited_properties["aboutUrl"],
64
+ property_url: inherited_properties["propertyUrl"],
65
+ value_url: inherited_properties["valueUrl"],
62
66
  required: inherited_properties["required"] || false,
63
67
  separator: inherited_properties["separator"],
68
+ ordered: inherited_properties["ordered"] || false,
69
+ default_name: column_properties["titles"] && column_properties["titles"][lang] ? column_properties["titles"][lang][0] : nil,
64
70
  titles: column_properties["titles"],
71
+ suppress_output: column_properties["suppressOutput"] ? column_properties["suppressOutput"] : false,
65
72
  virtual: column_properties["virtual"] || false,
66
73
  annotations: annotations,
67
74
  warnings: warnings
68
75
  )
69
76
  end
70
77
 
71
- def validate_header(header)
78
+ def validate_header(header, strict)
72
79
  reset
73
- valid_headers = @titles ? @titles.map{ |l,v| v if Column.languages_match(l, lang) }.flatten : []
74
- build_errors(:invalid_header, :schema, 1, @number, header, @titles) unless valid_headers.include? header
80
+ if strict || @titles
81
+ valid_headers = @titles ? @titles.map{ |l,v| v if Column.languages_match(l, lang) }.flatten : []
82
+ unless valid_headers.include? header
83
+ if strict
84
+ build_errors(:invalid_header, :schema, 1, @number, header, @titles)
85
+ else
86
+ build_warnings(:invalid_header, :schema, 1, @number, header, @titles)
87
+ end
88
+ end
89
+ end
75
90
  return valid?
76
91
  end
77
92
 
78
93
  def validate(string_value, row=nil)
79
94
  reset
80
- values = parse(string_value || "", row)
81
- # STDERR.puts "#{name} - #{string_value.inspect} - #{values.inspect}"
82
- values.each do |value|
83
- validate_required(value, row)
84
- validate_format(value, row)
85
- validate_length(value, row)
86
- validate_value(value, row)
87
- end unless values.nil?
88
- validate_required(values, row) if values.nil?
89
- return valid?
90
- end
91
-
92
- def parse(string_value, row=nil)
93
- return nil if null.include? string_value
94
- string_values = @separator.nil? ? [string_value] : string_value.split(@separator)
95
- values = []
96
- string_values.each do |s|
97
- value, warning = DATATYPE_PARSER[@datatype["base"] || @datatype["@id"]].call(s, @datatype["format"])
98
- if warning.nil?
99
- values << value
100
- else
101
- build_errors(warning, :schema, row, @number, s, @datatype)
102
- values << s
95
+ string_value = string_value || @default
96
+ if null.include? string_value
97
+ validate_required(nil, row)
98
+ values = nil
99
+ return values
100
+ else
101
+ string_values = @separator.nil? ? [string_value] : string_value.split(@separator)
102
+ values = []
103
+ string_values.each do |s|
104
+ invalid = false
105
+ value, warning = DATATYPE_PARSER[@datatype["base"] || @datatype["@id"]].call(s, @datatype["format"])
106
+ if warning.nil?
107
+ validate_required(value, row)
108
+ invalid = !validate_format(value, row) || invalid
109
+ invalid = !validate_length(value, row) || invalid
110
+ invalid = !validate_value(value, row) || invalid
111
+ values << (invalid ? { :invalid => s } : value)
112
+ else
113
+ build_errors(warning, :schema, row, @number, s, @datatype)
114
+ values << { :invalid => s }
115
+ end
103
116
  end
117
+ values = (values && @separator.nil?) ? values[0] : values
118
+ return values
104
119
  end
105
- return values
106
120
  end
107
121
 
108
122
  private
@@ -132,32 +146,65 @@ module Csvlint
132
146
  end
133
147
 
134
148
  def validate_required(value, row)
135
- build_errors(:required, :schema, row, number, value, { "required" => @required }) if @required && value.nil?
149
+ if @required && value.nil?
150
+ build_errors(:required, :schema, row, number, value, { "required" => @required })
151
+ return false
152
+ end
153
+ return true
136
154
  end
137
155
 
138
156
  def validate_length(value, row)
157
+ valid = true
139
158
  if datatype["length"] || datatype["minLength"] || datatype["maxLength"]
140
159
  length = value.length
141
160
  length = value.gsub(/==?$/,"").length * 3 / 4 if datatype["@id"] == "http://www.w3.org/2001/XMLSchema#base64Binary" || datatype["base"] == "http://www.w3.org/2001/XMLSchema#base64Binary"
142
161
  length = value.length / 2 if datatype["@id"] == "http://www.w3.org/2001/XMLSchema#hexBinary" || datatype["base"] == "http://www.w3.org/2001/XMLSchema#hexBinary"
143
162
 
144
- build_errors(:min_length, :schema, row, number, value, { "minLength" => datatype["minLength"] }) if datatype["minLength"] && length < datatype["minLength"]
145
- build_errors(:max_length, :schema, row, number, value, { "maxLength" => datatype["maxLength"] }) if datatype["maxLength"] && length > datatype["maxLength"]
146
- build_errors(:length, :schema, row, number, value, { "length" => datatype["length"] }) if datatype["length"] && length != datatype["length"]
163
+ if datatype["minLength"] && length < datatype["minLength"]
164
+ build_errors(:min_length, :schema, row, number, value, { "minLength" => datatype["minLength"] })
165
+ valid = false
166
+ end
167
+ if datatype["maxLength"] && length > datatype["maxLength"]
168
+ build_errors(:max_length, :schema, row, number, value, { "maxLength" => datatype["maxLength"] })
169
+ valid = false
170
+ end
171
+ if datatype["length"] && length != datatype["length"]
172
+ build_errors(:length, :schema, row, number, value, { "length" => datatype["length"] })
173
+ valid = false
174
+ end
147
175
  end
176
+ return valid
148
177
  end
149
178
 
150
179
  def validate_format(value, row)
151
180
  if datatype["format"]
152
- build_errors(:format, :schema, row, number, value, { "format" => datatype["format"] }) unless DATATYPE_FORMAT_VALIDATION[datatype["base"]].call(value, datatype["format"])
181
+ unless DATATYPE_FORMAT_VALIDATION[datatype["base"]].call(value, datatype["format"])
182
+ build_errors(:format, :schema, row, number, value, { "format" => datatype["format"] })
183
+ return false
184
+ end
153
185
  end
186
+ return true
154
187
  end
155
188
 
156
189
  def validate_value(value, row)
157
- build_errors(:min_inclusive, :schema, row, number, value, { "minInclusive" => datatype["minInclusive"] }) if datatype["minInclusive"] && value < datatype["minInclusive"]
158
- build_errors(:max_inclusive, :schema, row, number, value, { "maxInclusive" => datatype["maxInclusive"] }) if datatype["maxInclusive"] && value > datatype["maxInclusive"]
159
- build_errors(:min_exclusive, :schema, row, number, value, { "minExclusive" => datatype["minExclusive"] }) if datatype["minExclusive"] && value <= datatype["minExclusive"]
160
- build_errors(:max_exclusive, :schema, row, number, value, { "maxExclusive" => datatype["maxExclusive"] }) if datatype["maxExclusive"] && value >= datatype["maxExclusive"]
190
+ valid = true
191
+ if datatype["minInclusive"] && ((value.is_a? Hash) ? (value[:dateTime] < datatype["minInclusive"][:dateTime]) : (value < datatype["minInclusive"]))
192
+ build_errors(:min_inclusive, :schema, row, number, value, { "minInclusive" => datatype["minInclusive"] })
193
+ valid = false
194
+ end
195
+ if datatype["maxInclusive"] && ((value.is_a? Hash) ? (value[:dateTime] > datatype["maxInclusive"][:dateTime]) : (value > datatype["maxInclusive"]))
196
+ build_errors(:max_inclusive, :schema, row, number, value, { "maxInclusive" => datatype["maxInclusive"] })
197
+ valid = false
198
+ end
199
+ if datatype["minExclusive"] && ((value.is_a? Hash) ? (value[:dateTime] <= datatype["minExclusive"][:dateTime]) : (value <= datatype["minExclusive"]))
200
+ build_errors(:min_exclusive, :schema, row, number, value, { "minExclusive" => datatype["minExclusive"] })
201
+ valid = false
202
+ end
203
+ if datatype["maxExclusive"] && ((value.is_a? Hash) ? (value[:dateTime] >= datatype["maxExclusive"][:dateTime]) : (value >= datatype["maxExclusive"]))
204
+ build_errors(:max_exclusive, :schema, row, number, value, { "maxExclusive" => datatype["maxExclusive"] })
205
+ valid = false
206
+ end
207
+ return valid
161
208
  end
162
209
 
163
210
  REGEXP_VALIDATION = lambda { |value, format| value =~ format }
@@ -210,22 +257,23 @@ module Csvlint
210
257
  "http://www.w3.org/2001/XMLSchema#time" => NO_ADDITIONAL_VALIDATION
211
258
  }
212
259
 
260
+ TRIM_VALUE = lambda { |value, format| return value.strip, nil }
213
261
  ALL_VALUES_VALID = lambda { |value, format| return value, nil }
214
262
 
215
- NUMERIC_PARSER = lambda { |value, format|
216
- format = Csvlint::Csvw::NumberFormat.new() if format.nil?
263
+ NUMERIC_PARSER = lambda { |value, format, integer=false|
264
+ format = Csvlint::Csvw::NumberFormat.new(nil, nil, ".", integer) if format.nil?
217
265
  v = format.parse(value)
218
266
  return nil, :invalid_number if v.nil?
219
267
  return v, nil
220
268
  }
221
269
 
222
270
  DATATYPE_PARSER = {
223
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral" => ALL_VALUES_VALID,
224
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML" => ALL_VALUES_VALID,
225
- "http://www.w3.org/ns/csvw#JSON" => ALL_VALUES_VALID,
271
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral" => TRIM_VALUE,
272
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML" => TRIM_VALUE,
273
+ "http://www.w3.org/ns/csvw#JSON" => TRIM_VALUE,
226
274
  "http://www.w3.org/2001/XMLSchema#anyAtomicType" => ALL_VALUES_VALID,
227
- "http://www.w3.org/2001/XMLSchema#anyURI" => ALL_VALUES_VALID,
228
- "http://www.w3.org/2001/XMLSchema#base64Binary" => ALL_VALUES_VALID,
275
+ "http://www.w3.org/2001/XMLSchema#anyURI" => TRIM_VALUE,
276
+ "http://www.w3.org/2001/XMLSchema#base64Binary" => TRIM_VALUE,
229
277
  "http://www.w3.org/2001/XMLSchema#boolean" => lambda { |value, format|
230
278
  if format.nil?
231
279
  return true, nil if ["true", "1"].include? value
@@ -243,11 +291,11 @@ module Csvlint
243
291
  "http://www.w3.org/2001/XMLSchema#dateTimeStamp" =>
244
292
  create_date_parser("http://www.w3.org/2001/XMLSchema#dateTimeStamp", :invalid_date_time_stamp),
245
293
  "http://www.w3.org/2001/XMLSchema#decimal" => lambda { |value, format|
246
- return nil, :invalid_decimal if value =~ /(E|^(NaN|INF|-INF)$)/
294
+ return nil, :invalid_decimal if value =~ /(E|e|^(NaN|INF|-INF)$)/
247
295
  return NUMERIC_PARSER.call(value, format)
248
296
  },
249
297
  "http://www.w3.org/2001/XMLSchema#integer" => lambda { |value, format|
250
- v, w = NUMERIC_PARSER.call(value, format)
298
+ v, w = NUMERIC_PARSER.call(value, format, true)
251
299
  return v, :invalid_integer unless w.nil?
252
300
  return nil, :invalid_integer unless v.kind_of? Integer
253
301
  return v, w
@@ -343,14 +391,14 @@ module Csvlint
343
391
  create_date_parser("http://www.w3.org/2001/XMLSchema#gYear", :invalid_gYear),
344
392
  "http://www.w3.org/2001/XMLSchema#gYearMonth" =>
345
393
  create_date_parser("http://www.w3.org/2001/XMLSchema#gYearMonth", :invalid_gYearMonth),
346
- "http://www.w3.org/2001/XMLSchema#hexBinary" => ALL_VALUES_VALID,
347
- "http://www.w3.org/2001/XMLSchema#QName" => ALL_VALUES_VALID,
394
+ "http://www.w3.org/2001/XMLSchema#hexBinary" => TRIM_VALUE,
395
+ "http://www.w3.org/2001/XMLSchema#QName" => TRIM_VALUE,
348
396
  "http://www.w3.org/2001/XMLSchema#string" => ALL_VALUES_VALID,
349
- "http://www.w3.org/2001/XMLSchema#normalizedString" => ALL_VALUES_VALID,
350
- "http://www.w3.org/2001/XMLSchema#token" => ALL_VALUES_VALID,
351
- "http://www.w3.org/2001/XMLSchema#language" => ALL_VALUES_VALID,
352
- "http://www.w3.org/2001/XMLSchema#Name" => ALL_VALUES_VALID,
353
- "http://www.w3.org/2001/XMLSchema#NMTOKEN" => ALL_VALUES_VALID,
397
+ "http://www.w3.org/2001/XMLSchema#normalizedString" => TRIM_VALUE,
398
+ "http://www.w3.org/2001/XMLSchema#token" => TRIM_VALUE,
399
+ "http://www.w3.org/2001/XMLSchema#language" => TRIM_VALUE,
400
+ "http://www.w3.org/2001/XMLSchema#Name" => TRIM_VALUE,
401
+ "http://www.w3.org/2001/XMLSchema#NMTOKEN" => TRIM_VALUE,
354
402
  "http://www.w3.org/2001/XMLSchema#time" =>
355
403
  create_date_parser("http://www.w3.org/2001/XMLSchema#time", :invalid_time)
356
404
  }