rdf-n3 0.0.3 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/lib/rdf/n3/patches/literal_normalization.rb +126 -99
- data/lib/rdf/n3/reader.rb +10 -9
- data/lib/rdf/n3/version.rb +2 -2
- data/lib/rdf/n3/writer.rb +1 -1
- data/lib/rdf/n3.rb +0 -2
- data/rdf-n3.gemspec +13 -17
- data/spec/literal_spec.rb +22 -343
- data/spec/n3reader_spec.rb +19 -19
- data/spec/spec_helper.rb +1 -0
- metadata +12 -33
- data/lib/rdf/n3/patches/literal_hacks.rb +0 -23
- data/lib/rdf/n3/patches/rdf_escape.rb +0 -131
- data/spec/turtle_serializer_spec.rb +0 -226
@@ -1,131 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
require 'iconv'
|
3
|
-
|
4
|
-
class String
|
5
|
-
#private
|
6
|
-
# "Borrowed" from JSON utf8_to_json
|
7
|
-
RDF_MAP = {
|
8
|
-
"\x0" => '\u0000',
|
9
|
-
"\x1" => '\u0001',
|
10
|
-
"\x2" => '\u0002',
|
11
|
-
"\x3" => '\u0003',
|
12
|
-
"\x4" => '\u0004',
|
13
|
-
"\x5" => '\u0005',
|
14
|
-
"\x6" => '\u0006',
|
15
|
-
"\x7" => '\u0007',
|
16
|
-
"\b" => '\b',
|
17
|
-
"\t" => '\t',
|
18
|
-
"\n" => '\n',
|
19
|
-
"\xb" => '\u000B',
|
20
|
-
"\f" => '\f',
|
21
|
-
"\r" => '\r',
|
22
|
-
"\xe" => '\u000E',
|
23
|
-
"\xf" => '\u000F',
|
24
|
-
"\x10" => '\u0010',
|
25
|
-
"\x11" => '\u0011',
|
26
|
-
"\x12" => '\u0012',
|
27
|
-
"\x13" => '\u0013',
|
28
|
-
"\x14" => '\u0014',
|
29
|
-
"\x15" => '\u0015',
|
30
|
-
"\x16" => '\u0016',
|
31
|
-
"\x17" => '\u0017',
|
32
|
-
"\x18" => '\u0018',
|
33
|
-
"\x19" => '\u0019',
|
34
|
-
"\x1a" => '\u001A',
|
35
|
-
"\x1b" => '\u001B',
|
36
|
-
"\x1c" => '\u001C',
|
37
|
-
"\x1d" => '\u001D',
|
38
|
-
"\x1e" => '\u001E',
|
39
|
-
"\x1f" => '\u001F',
|
40
|
-
'"' => '\"',
|
41
|
-
'\\' => '\\\\',
|
42
|
-
'/' => '/',
|
43
|
-
} # :nodoc:
|
44
|
-
|
45
|
-
if defined?(::Encoding)
|
46
|
-
# Funky way to define constant, but if parsed in 1.8 it generates an 'invalid regular expression' error otherwise
|
47
|
-
eval %(ESCAPE_RE = %r([\u{80}-\u{10ffff}]))
|
48
|
-
else
|
49
|
-
ESCAPE_RE = %r(
|
50
|
-
[\xc2-\xdf][\x80-\xbf] |
|
51
|
-
[\xe0-\xef][\x80-\xbf]{2} |
|
52
|
-
[\xf0-\xf4][\x80-\xbf]{3}
|
53
|
-
)nx
|
54
|
-
end
|
55
|
-
|
56
|
-
# Convert a UTF8 encoded Ruby string _string_ to an escaped string, encoded with
|
57
|
-
# UTF16 big endian characters as \U????, and return it.
|
58
|
-
#
|
59
|
-
# \\:: Backslash
|
60
|
-
# \':: Single quote
|
61
|
-
# \":: Double quot
|
62
|
-
# \n:: ASCII Linefeed
|
63
|
-
# \r:: ASCII Carriage Return
|
64
|
-
# \t:: ASCCII Horizontal Tab
|
65
|
-
# \uhhhh:: character in BMP with Unicode value U+hhhh
|
66
|
-
# \U00hhhhhh:: character in plane 1-16 with Unicode value U+hhhhhh
|
67
|
-
def rdf_escape
|
68
|
-
string = self + '' # XXX workaround: avoid buffer sharing
|
69
|
-
string.gsub!(/["\\\/\x0-\x1f]/) { RDF_MAP[$&] }
|
70
|
-
if defined?(::Encoding)
|
71
|
-
string.force_encoding(Encoding::UTF_8)
|
72
|
-
string.gsub!(ESCAPE_RE) { |c|
|
73
|
-
s = c.dump.sub(/\"\\u\{(.+)\}\"/, '\1').upcase
|
74
|
-
(s.length <= 4 ? "\\u0000"[0,6-s.length] : "\\U00000000"[0,10-s.length]) + s
|
75
|
-
}
|
76
|
-
string.force_encoding(Encoding::ASCII_8BIT)
|
77
|
-
else
|
78
|
-
string.gsub!(ESCAPE_RE) { |c|
|
79
|
-
s = Iconv.new('utf-16be', 'utf-8').iconv(c).unpack('H*').first.upcase
|
80
|
-
"\\u" + s
|
81
|
-
}
|
82
|
-
end
|
83
|
-
string
|
84
|
-
end
|
85
|
-
|
86
|
-
# Unescape characters in strings.
|
87
|
-
RDF_UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
|
88
|
-
RDF_UNESCAPE_MAP.update({
|
89
|
-
?" => '"',
|
90
|
-
?\\ => '\\',
|
91
|
-
?/ => '/',
|
92
|
-
?b => "\b",
|
93
|
-
?f => "\f",
|
94
|
-
?n => "\n",
|
95
|
-
?r => "\r",
|
96
|
-
?t => "\t",
|
97
|
-
?u => nil,
|
98
|
-
})
|
99
|
-
|
100
|
-
if defined?(::Encoding)
|
101
|
-
UNESCAPE_RE = %r(
|
102
|
-
(?:\\[\\bfnrt"/]) # Escaped control characters, " and /
|
103
|
-
|(?:\\U00\h{6}) # 6 byte escaped Unicode
|
104
|
-
|(?:\\u\h{4}) # 4 byte escaped Unicode
|
105
|
-
)x
|
106
|
-
else
|
107
|
-
UNESCAPE_RE = %r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n
|
108
|
-
end
|
109
|
-
|
110
|
-
# Reverse operation of escape
|
111
|
-
# From JSON parser
|
112
|
-
def rdf_unescape
|
113
|
-
return '' if self.empty?
|
114
|
-
string = self.gsub(UNESCAPE_RE) do |c|
|
115
|
-
case c[1,1]
|
116
|
-
when 'U'
|
117
|
-
raise RDF::ReaderError, "Long Unicode escapes no supported in Ruby 1.8" unless defined?(::Encoding)
|
118
|
-
eval(c.sub(/\\U00(\h+)/, '"\u{\1}"'))
|
119
|
-
when 'u'
|
120
|
-
bytes = [c[2, 2].to_i(16), c[4, 2].to_i(16)]
|
121
|
-
Iconv.new('utf-8', 'utf-16').iconv(bytes.pack("C*"))
|
122
|
-
else
|
123
|
-
RDF_UNESCAPE_MAP[c[1]]
|
124
|
-
end
|
125
|
-
end
|
126
|
-
string.force_encoding(Encoding::UTF_8) if defined?(::Encoding)
|
127
|
-
string
|
128
|
-
rescue Iconv::Failure => e
|
129
|
-
raise RDF::ReaderError, "Caught #{e.class}: #{e}"
|
130
|
-
end
|
131
|
-
end unless String.method_defined?(:rdf_escape)
|
@@ -1,226 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
-
include RdfContext
|
3
|
-
|
4
|
-
describe "Turtle Serializer" do
|
5
|
-
describe "simple tests" do
|
6
|
-
it "should use full URIs without base" do
|
7
|
-
input = %(<http://a/b> <http://a/c> <http://a/d> .)
|
8
|
-
serialize(input, nil, %r(^<http://a/b> <http://a/c> <http://a/d> \.$))
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should use relative URIs with base" do
|
12
|
-
input = %(<http://a/b> <http://a/c> <http://a/d> .)
|
13
|
-
serialize(input, "http://a/",
|
14
|
-
%r(^@base <http://a/> \.$),
|
15
|
-
%r(^<b> <c> <d> \.$)
|
16
|
-
)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should use qname URIs with prefix" do
|
20
|
-
input = %(@prefix a: <http://a/> . <http://a/b> <http://a/c> <http://a/d> .)
|
21
|
-
serialize(input, nil,
|
22
|
-
%r(^@prefix a: <http://a/> \.$),
|
23
|
-
%r(^a:b a:c a:d \.$)
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should use qname URIs with empty prefix" do
|
28
|
-
input = %(@prefix : <http://a/> . <http://a/b> <http://a/c> <http://a/d> .)
|
29
|
-
serialize(input, nil,
|
30
|
-
%r(^@prefix : <http://a/> \.$),
|
31
|
-
%r(^:b :c :d \.$)
|
32
|
-
)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should order properties" do
|
36
|
-
input = %(
|
37
|
-
@prefix : <http://a/> .
|
38
|
-
@prefix dc: <http://purl.org/dc/elements/1.1/> .
|
39
|
-
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
40
|
-
:b :c :d .
|
41
|
-
:b dc:title "title" .
|
42
|
-
:b a :class .
|
43
|
-
:b rdfs:label "label" .
|
44
|
-
)
|
45
|
-
serialize(input, nil,
|
46
|
-
%r(^:b a :class;$),
|
47
|
-
%r(^\s+rdfs:label "label"),
|
48
|
-
%r(^\s+dc:title \"title\"),
|
49
|
-
%r(^\s+:c :d)
|
50
|
-
)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should generate object list" do
|
54
|
-
input = %(@prefix : <http://a/> . :b :c :d, :e .)
|
55
|
-
serialize(input, nil,
|
56
|
-
%r(^@prefix : <http://a/> \.$),
|
57
|
-
%r(^:b :c :d,$),
|
58
|
-
%r(^\s+:e \.$)
|
59
|
-
)
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should generate property list" do
|
63
|
-
input = %(@prefix : <http://a/> . :b :c :d; :e :f .)
|
64
|
-
serialize(input, nil,
|
65
|
-
%r(^@prefix : <http://a/> \.$),
|
66
|
-
%r(^:b :c :d;$),
|
67
|
-
%r(^\s+:e :f \.$)
|
68
|
-
)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
describe "anons" do
|
73
|
-
it "should generate bare anon" do
|
74
|
-
input = %(@prefix : <http://a/> . [:a :b] .)
|
75
|
-
serialize(input, nil,
|
76
|
-
%r(^\s*\[ :a :b\] \.$)
|
77
|
-
)
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should generate anon as subject" do
|
81
|
-
input = %(@prefix : <http://a/> . [:a :b] :c :d .)
|
82
|
-
serialize(input, nil,
|
83
|
-
%r(^\s*\[ :a :b;$),
|
84
|
-
%r(^\s+:c :d\] \.$)
|
85
|
-
)
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should generate anon as object" do
|
89
|
-
input = %(@prefix : <http://a/> . :a :b [:c :d] .)
|
90
|
-
serialize(input, nil,
|
91
|
-
%r(^\s*\:a :b \[ :c :d\] \.$)
|
92
|
-
)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe "lists" do
|
97
|
-
it "should generate bare list" do
|
98
|
-
input = %(@prefix : <http://a/> . (:a :b) .)
|
99
|
-
serialize(input, nil,
|
100
|
-
%r(^\(:a :b\) \.$)
|
101
|
-
)
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should generate literal list" do
|
105
|
-
input = %(@prefix : <http://a/> . :a :b ( "apple" "banana" ) .)
|
106
|
-
serialize(input, nil,
|
107
|
-
%r(^:a :b \("apple" "banana"\) \.$)
|
108
|
-
)
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should generate empty list" do
|
112
|
-
input = %(@prefix : <http://a/> . :a :b () .)
|
113
|
-
serialize(input, nil,
|
114
|
-
%r(^:a :b \(\) \.$)
|
115
|
-
)
|
116
|
-
end
|
117
|
-
|
118
|
-
it "should generate empty list(2)" do
|
119
|
-
input = %(@prefix : <http://a/> . :emptyList = () .)
|
120
|
-
serialize(input, nil,
|
121
|
-
%r(^:emptyList (<.*sameAs>|owl:sameAs) \(\) \.$)
|
122
|
-
)
|
123
|
-
end
|
124
|
-
|
125
|
-
it "should generate empty list as subject" do
|
126
|
-
input = %(@prefix : <http://a/> . () :a :b .)
|
127
|
-
serialize(input, nil,
|
128
|
-
%r(^\(\) :a :b \.$)
|
129
|
-
)
|
130
|
-
end
|
131
|
-
|
132
|
-
it "should generate list as subject" do
|
133
|
-
input = %(@prefix : <http://a/> . (:a) :b :c .)
|
134
|
-
serialize(input, nil,
|
135
|
-
%r(^\(:a\) :b :c \.$)
|
136
|
-
)
|
137
|
-
end
|
138
|
-
|
139
|
-
it "should generate list of empties" do
|
140
|
-
input = %(@prefix : <http://a/> . :listOf2Empties = (() ()) .)
|
141
|
-
serialize(input, nil,
|
142
|
-
%r(^:listOf2Empties (<.*sameAs>|owl:sameAs) \(\(\) \(\)\) \.$)
|
143
|
-
)
|
144
|
-
end
|
145
|
-
|
146
|
-
it "should generate list anon" do
|
147
|
-
input = %(@prefix : <http://a/> . :twoAnons = ([a :mother] [a :father]) .)
|
148
|
-
serialize(input, nil,
|
149
|
-
%r(^:twoAnons (<.*sameAs>|owl:sameAs) \(\[\s*a :mother\] \[\s*a :father\]\) \.$)
|
150
|
-
)
|
151
|
-
end
|
152
|
-
|
153
|
-
it "should generate owl:unionOf list" do
|
154
|
-
input = %(
|
155
|
-
@prefix : <http://a/> .
|
156
|
-
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
157
|
-
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
158
|
-
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
159
|
-
:a rdfs:domain [
|
160
|
-
a owl:Class;
|
161
|
-
owl:unionOf [
|
162
|
-
a owl:Class;
|
163
|
-
rdf:first :b;
|
164
|
-
rdf:rest [
|
165
|
-
a owl:Class;
|
166
|
-
rdf:first :c;
|
167
|
-
rdf:rest rdf:nil
|
168
|
-
]
|
169
|
-
]
|
170
|
-
] .
|
171
|
-
)
|
172
|
-
serialize(input, nil,
|
173
|
-
%r(:a rdfs:domain \[\s*a owl:Class;\s+owl:unionOf\s+\(:b\s+:c\)\]\s*\.$)m
|
174
|
-
)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
# W3C Turtle Test suite from http://www.w3.org/2000/10/swap/test/regression.n3
|
179
|
-
describe "w3c turtle tests" do
|
180
|
-
require 'rdf_helper'
|
181
|
-
|
182
|
-
def self.positive_tests
|
183
|
-
RdfHelper::TestCase.test_cases(TURTLE_TEST, TURTLE_DIR) rescue []
|
184
|
-
end
|
185
|
-
|
186
|
-
positive_tests.each do |t|
|
187
|
-
#puts t.inspect
|
188
|
-
#next unless t.name == "test-04"
|
189
|
-
|
190
|
-
specify "#{t.name}: " + (t.description || "#{t.inputDocument}") do
|
191
|
-
# Skip tests for very long files, too long
|
192
|
-
if %w(test-14 test-15 test-16 rdfq-results).include?(t.name)
|
193
|
-
pending("Skip very long input file")
|
194
|
-
elsif !defined?(::Encoding) && %w(test-18).include?(t.name)
|
195
|
-
pending("Not supported in Ruby 1.8")
|
196
|
-
elsif %w(test-29).include?(t.name)
|
197
|
-
pending("Silly test")
|
198
|
-
else
|
199
|
-
begin
|
200
|
-
t.run_test do |rdf_string, parser|
|
201
|
-
parser.parse(rdf_string, t.about.uri.to_s, :strict => true, :debug => [])
|
202
|
-
parser.graph.serialize(:format => :ttl, :base => t.about.uri.to_s)
|
203
|
-
t.compare = :none
|
204
|
-
end
|
205
|
-
#rescue #Spec::Expectations::ExpectationNotMetError => e
|
206
|
-
# pending() { raise }
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
# Serialize ntstr to a string and compare against regexps
|
214
|
-
def serialize(ntstr, base = nil, *regexps)
|
215
|
-
g = Graph.new
|
216
|
-
g.parse(ntstr, base)
|
217
|
-
result = g.serialize(:format => :ttl, :base => base)
|
218
|
-
puts result if $verbose
|
219
|
-
|
220
|
-
regexps.each do |re|
|
221
|
-
result.should =~ re
|
222
|
-
end
|
223
|
-
|
224
|
-
result
|
225
|
-
end
|
226
|
-
end
|