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