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 +8 -8
- data/.gitattributes +1 -1
- data/.gitignore +1 -1
- data/csvlint.gemspec +2 -0
- data/features/fixtures/w3.org/.well-known/csvm +4 -0
- data/features/step_definitions/validation_errors_steps.rb +1 -1
- data/features/support/earl_formatter.rb +66 -0
- data/features/support/load_tests.rb +20 -15
- data/lib/csvlint/csvw/column.rb +103 -55
- data/lib/csvlint/csvw/date_format.rb +49 -16
- data/lib/csvlint/csvw/number_format.rb +36 -21
- data/lib/csvlint/csvw/property_checker.rb +90 -45
- data/lib/csvlint/csvw/table.rb +57 -39
- data/lib/csvlint/csvw/table_group.rb +9 -9
- data/lib/csvlint/schema.rb +2 -2
- data/lib/csvlint/validate.rb +10 -13
- data/lib/csvlint/version.rb +1 -1
- data/spec/csvw/column_spec.rb +6 -6
- data/spec/csvw/date_format_spec.rb +10 -10
- data/spec/csvw/number_format_spec.rb +29 -0
- metadata +34 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MTJlZWM1ZDA0ZDMzMjBkM2I1OGUxYjM1NTIxZTA1NWVkODJlMDFiYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MWE1MWYzZjk3YjgwMTJhNzBjZGM4NTMyOGYzYTU1ZWM4ZDc4NTI2YQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MWU5NTAxZDVjMGI3YTNiYTBlNTJmODkxNTBkYzdiN2ExN2E3NGE2ZjI5M2Nl
|
10
|
+
ZGY0OWM3ZTVjODNiNjcyZDMwODhhNTc3ODIyZGMyMzUzYWE2ZTMyZmFmNGIw
|
11
|
+
NDFiYzc5YzNlNTFlODQ1ODE1YzZkMDU0MDdkMzE3MmVlNWUyYmU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjBhYTU1ZWMzNjcxMmU1NjU1ZjZkYTE5M2YwOTQ5NzYyOWYzNmM2NzkxNWJk
|
14
|
+
Y2VlM2JkMmRlYmNhNzM5MGI0ZDg2YWQzOTNhYzg1YjAyNDRiNTFiNmRlZjk4
|
15
|
+
Nzc0YjJlOWM0MGVmMjAzZTBiZjQwZTc4MTU5YTVjMGFiZDFjNmQ=
|
data/.gitattributes
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
# Don't
|
1
|
+
# Don't mess with my CSV files
|
2
2
|
*.csv binary
|
data/.gitignore
CHANGED
data/csvlint.gemspec
CHANGED
@@ -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
|
@@ -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
|
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://
|
5
|
+
BASE_URI = "http://www.w3.org/2013/csvw/tests/"
|
6
6
|
BASE_PATH = File.join(File.dirname(__FILE__), "..", "fixtures", "csvw")
|
7
|
-
|
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://
|
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(
|
56
|
-
file.puts "# Auto-generated file based on standard validation CSVW tests from http://
|
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://
|
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
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
112
|
+
file.puts "\t\tThen there should be errors"
|
108
113
|
else
|
109
|
-
|
110
|
-
|
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?
|
119
|
+
end unless File.exist? VALIDATION_FEATURE_FILE_PATH
|
data/lib/csvlint/csvw/column.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
74
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
-
|
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
|
-
|
145
|
-
|
146
|
-
|
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
|
-
|
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
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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" =>
|
224
|
-
"http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML" =>
|
225
|
-
"http://www.w3.org/ns/csvw#JSON" =>
|
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" =>
|
228
|
-
"http://www.w3.org/2001/XMLSchema#base64Binary" =>
|
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" =>
|
347
|
-
"http://www.w3.org/2001/XMLSchema#QName" =>
|
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" =>
|
350
|
-
"http://www.w3.org/2001/XMLSchema#token" =>
|
351
|
-
"http://www.w3.org/2001/XMLSchema#language" =>
|
352
|
-
"http://www.w3.org/2001/XMLSchema#Name" =>
|
353
|
-
"http://www.w3.org/2001/XMLSchema#NMTOKEN" =>
|
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
|
}
|