csvlint 0.2.6 → 0.3.0

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,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
  }