rdf 0.0.3 → 0.0.4
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.
- data/README +32 -0
- data/VERSION +1 -1
- data/bin/rdf +17 -26
- data/bin/rdf-count +11 -0
- data/bin/rdf-lengths +9 -0
- data/bin/rdf-objects +9 -0
- data/bin/rdf-predicates +9 -0
- data/bin/rdf-subjects +9 -0
- data/lib/df.rb +1 -0
- data/lib/rdf.rb +33 -4
- data/lib/rdf/cli.rb +73 -0
- data/lib/rdf/graph.rb +189 -0
- data/lib/rdf/literal.rb +96 -0
- data/lib/rdf/node.rb +32 -0
- data/lib/rdf/reader.rb +52 -5
- data/lib/rdf/reader/ntriples.rb +23 -15
- data/lib/rdf/resource.rb +10 -0
- data/lib/rdf/statement.rb +76 -8
- data/lib/rdf/uri.rb +65 -1
- data/lib/rdf/value.rb +25 -0
- data/lib/rdf/version.rb +6 -1
- data/lib/rdf/vocabulary.rb +42 -7
- data/lib/rdf/vocabulary/cc.rb +3 -1
- data/lib/rdf/vocabulary/dc.rb +3 -1
- data/lib/rdf/vocabulary/doap.rb +3 -1
- data/lib/rdf/vocabulary/exif.rb +3 -1
- data/lib/rdf/vocabulary/foaf.rb +3 -1
- data/lib/rdf/vocabulary/http.rb +3 -1
- data/lib/rdf/vocabulary/owl.rb +3 -1
- data/lib/rdf/vocabulary/rdf.rb +3 -1
- data/lib/rdf/vocabulary/rdfs.rb +3 -1
- data/lib/rdf/vocabulary/rss.rb +3 -1
- data/lib/rdf/vocabulary/sioc.rb +3 -1
- data/lib/rdf/vocabulary/skos.rb +3 -1
- data/lib/rdf/vocabulary/wot.rb +3 -1
- data/lib/rdf/vocabulary/xhtml.rb +3 -1
- data/lib/rdf/vocabulary/xsd.rb +3 -1
- data/lib/rdf/writer.rb +220 -0
- data/lib/rdf/writer/ntriples.rb +50 -0
- metadata +17 -2
data/lib/rdf/literal.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# An RDF literal.
|
4
|
+
class Literal < Value
|
5
|
+
# @return [String] The normalized string representation of the value.
|
6
|
+
attr_accessor :value
|
7
|
+
|
8
|
+
# @return [Symbol] The language tag (optional).
|
9
|
+
attr_accessor :language
|
10
|
+
|
11
|
+
# @return [URI] The XML Schema datatype URI (optional).
|
12
|
+
attr_accessor :datatype
|
13
|
+
|
14
|
+
##
|
15
|
+
# @param [Object]
|
16
|
+
# @option options [Symbol] :language (nil)
|
17
|
+
# @option options [URI] :datatype (nil)
|
18
|
+
def initialize(value, options = {})
|
19
|
+
@value = value
|
20
|
+
@language = options[:language] ? options[:language].to_s.to_sym : nil
|
21
|
+
|
22
|
+
if datatype = options[:datatype]
|
23
|
+
@datatype = datatype.respond_to?(:to_uri) ? datatype.to_uri : URI.new(datatype.to_s)
|
24
|
+
else
|
25
|
+
@datatype = case value
|
26
|
+
when String then nil # implicit XSD.string
|
27
|
+
when TrueClass then XSD.boolean
|
28
|
+
when FalseClass then XSD.boolean
|
29
|
+
when Fixnum then XSD.int
|
30
|
+
when Integer then XSD.long # FIXME
|
31
|
+
when Float
|
32
|
+
@value = case
|
33
|
+
when value.nan? then 'NaN'
|
34
|
+
when value.infinite? then value.to_s[0...-'inity'.length].upcase
|
35
|
+
else value.to_f
|
36
|
+
end
|
37
|
+
XSD.double
|
38
|
+
when Time, Date, DateTime
|
39
|
+
require 'time'
|
40
|
+
@value = value.respond_to?(:xmlschema) ? value.xmlschema : value.to_s
|
41
|
+
case value
|
42
|
+
when DateTime then XSD.dateTime
|
43
|
+
when Date then XSD.date
|
44
|
+
when Time then XSD.dateTime
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
@value = @value.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# @return [Boolean]
|
54
|
+
def eql?(other)
|
55
|
+
other.is_a?(Literal) && self == other
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# @return [Boolean]
|
60
|
+
def ==(other)
|
61
|
+
case other
|
62
|
+
when Literal
|
63
|
+
value.eql?(other.value) &&
|
64
|
+
language.eql?(other.language) &&
|
65
|
+
datatype.eql?(other.datatype)
|
66
|
+
when String
|
67
|
+
value.eql?(other) &&
|
68
|
+
language.nil? &&
|
69
|
+
datatype.nil?
|
70
|
+
else false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# @return [Boolean]
|
76
|
+
def plain?
|
77
|
+
language.nil? && datatype.nil?
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# @return [Boolean]
|
82
|
+
def typed?
|
83
|
+
!datatype.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# @return [String]
|
88
|
+
def to_s
|
89
|
+
quoted = value # FIXME
|
90
|
+
output = "\"#{quoted}\""
|
91
|
+
output << "@#{language}" if language
|
92
|
+
output << "^^<#{datatype}>" if datatype
|
93
|
+
output
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/rdf/node.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module RDF
|
2
|
+
##
|
3
|
+
# An RDF blank node, also known as an unlabeled node.
|
4
|
+
class Node < Resource
|
5
|
+
# @return [String]
|
6
|
+
attr_accessor :id
|
7
|
+
|
8
|
+
##
|
9
|
+
# @param [#to_s]
|
10
|
+
def initialize(id = nil)
|
11
|
+
@id = (id || object_id).to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [Boolean]
|
16
|
+
def anonymous?() true end
|
17
|
+
|
18
|
+
##
|
19
|
+
# @return [Boolean]
|
20
|
+
def labeled?() !unlabeled? end
|
21
|
+
|
22
|
+
##
|
23
|
+
# @return [Boolean]
|
24
|
+
def unlabeled?() anonymous? end
|
25
|
+
|
26
|
+
##
|
27
|
+
# @return [String]
|
28
|
+
def to_s
|
29
|
+
"_:%s" % id.to_s
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/rdf/reader.rb
CHANGED
@@ -1,34 +1,53 @@
|
|
1
1
|
module RDF
|
2
|
-
|
3
|
-
|
2
|
+
##
|
3
|
+
# An RDF parser.
|
4
|
+
#
|
5
|
+
# @abstract
|
4
6
|
class Reader
|
5
7
|
autoload :NTriples, 'rdf/reader/ntriples'
|
6
8
|
|
7
9
|
include Enumerable
|
8
10
|
|
9
|
-
@@subclasses
|
10
|
-
@@file_extensions
|
11
|
-
@@content_types
|
11
|
+
@@subclasses = []
|
12
|
+
@@file_extensions = {}
|
13
|
+
@@content_types = {}
|
12
14
|
@@content_encoding = {}
|
13
15
|
|
16
|
+
##
|
17
|
+
# Enumerates known RDF reader classes.
|
18
|
+
#
|
19
|
+
# @yield [klass]
|
20
|
+
# @yieldparam [Class]
|
14
21
|
def self.each(&block)
|
15
22
|
!block_given? ? @@subclasses : @@subclasses.each { |klass| yield klass }
|
16
23
|
end
|
17
24
|
|
25
|
+
##
|
26
|
+
# @return [{String => Symbol}]
|
18
27
|
def self.content_types
|
19
28
|
@@content_types
|
20
29
|
end
|
21
30
|
|
31
|
+
##
|
32
|
+
# @return [{Symbol => String}]
|
22
33
|
def self.file_extensions
|
23
34
|
@@file_extensions
|
24
35
|
end
|
25
36
|
|
37
|
+
##
|
38
|
+
# @param [Symbol] format
|
39
|
+
# @return [Class]
|
26
40
|
def self.for(format)
|
27
41
|
klass = case format.to_s.downcase.to_sym
|
28
42
|
when :ntriples then RDF::Reader::NTriples
|
29
43
|
end
|
30
44
|
end
|
31
45
|
|
46
|
+
##
|
47
|
+
# @param [String] filename
|
48
|
+
# @option options [Symbol] :format (:ntriples)
|
49
|
+
# @yield [reader]
|
50
|
+
# @yieldparam [Reader]
|
32
51
|
def self.open(filename, options = {}, &block)
|
33
52
|
options[:format] ||= :ntriples # FIXME
|
34
53
|
|
@@ -37,6 +56,10 @@ module RDF
|
|
37
56
|
end
|
38
57
|
end
|
39
58
|
|
59
|
+
##
|
60
|
+
# @param [IO, String] input
|
61
|
+
# @yield [reader]
|
62
|
+
# @yieldparam [Reader]
|
40
63
|
def initialize(input = $stdin, options = {}, &block)
|
41
64
|
@options = options
|
42
65
|
@nodes = {}
|
@@ -47,35 +70,57 @@ module RDF
|
|
47
70
|
block.call(self) if block_given?
|
48
71
|
end
|
49
72
|
|
73
|
+
##
|
74
|
+
# @yield [statement]
|
75
|
+
# @yieldparam [Statement]
|
76
|
+
# @return [Reader]
|
50
77
|
def each(&block)
|
51
78
|
each_statement(&block)
|
52
79
|
end
|
53
80
|
|
81
|
+
##
|
82
|
+
# @yield [statement]
|
83
|
+
# @yieldparam [Statement]
|
84
|
+
# @return [Reader]
|
54
85
|
def each_statement(&block)
|
55
86
|
each_triple { |*triple| block.call(Statement.new(*triple)) }
|
87
|
+
self
|
56
88
|
end
|
57
89
|
|
90
|
+
##
|
91
|
+
# @yield [triple]
|
92
|
+
# @yieldparam [Array]
|
93
|
+
# @return [Reader]
|
58
94
|
def each_triple(&block)
|
59
95
|
begin
|
60
96
|
loop { block.call(*read_triple) }
|
61
97
|
rescue EOFError => e
|
62
98
|
end
|
99
|
+
self
|
63
100
|
end
|
64
101
|
|
65
102
|
protected
|
66
103
|
|
104
|
+
##
|
105
|
+
# @raise [NotImplementedError] unless implemented in subclass
|
67
106
|
def read_triple
|
68
107
|
raise NotImplementedError
|
69
108
|
end
|
70
109
|
|
110
|
+
##
|
111
|
+
# @raise [ReaderError]
|
71
112
|
def fail_subject
|
72
113
|
raise RDF::ReaderError, "expected subject in #{@input.inspect} line #{lineno}"
|
73
114
|
end
|
74
115
|
|
116
|
+
##
|
117
|
+
# @raise [ReaderError]
|
75
118
|
def fail_predicate
|
76
119
|
raise RDF::ReaderError, "expected predicate in #{@input.inspect} line #{lineno}"
|
77
120
|
end
|
78
121
|
|
122
|
+
##
|
123
|
+
# @raise [ReaderError]
|
79
124
|
def fail_object
|
80
125
|
raise RDF::ReaderError, "expected object in #{@input.inspect} line #{lineno}"
|
81
126
|
end
|
@@ -125,4 +170,6 @@ module RDF
|
|
125
170
|
end
|
126
171
|
|
127
172
|
end
|
173
|
+
|
174
|
+
class ReaderError < IOError; end
|
128
175
|
end
|
data/lib/rdf/reader/ntriples.rb
CHANGED
@@ -1,15 +1,18 @@
|
|
1
1
|
module RDF class Reader
|
2
|
-
|
2
|
+
##
|
3
|
+
# An N-Triples parser.
|
4
|
+
#
|
5
|
+
# @see http://www.w3.org/TR/rdf-testcases/#ntriples
|
3
6
|
class NTriples < Reader
|
4
|
-
|
5
7
|
content_type 'text/plain', :extension => :nt
|
6
8
|
content_encoding 'ascii'
|
7
9
|
|
8
10
|
protected
|
9
11
|
|
12
|
+
##
|
13
|
+
# @return [Array, nil]
|
14
|
+
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
|
10
15
|
def read_triple
|
11
|
-
# <http://www.w3.org/TR/rdf-testcases/#ntrip_grammar>
|
12
|
-
|
13
16
|
loop do
|
14
17
|
readline.strip! # EOFError thrown on end of input
|
15
18
|
|
@@ -22,31 +25,35 @@ module RDF class Reader
|
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
28
|
+
##
|
29
|
+
# @return [Boolean]
|
30
|
+
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (comment)
|
25
31
|
def read_comment
|
26
|
-
# <http://www.w3.org/TR/rdf-testcases/#ntrip_grammar> (comment)
|
27
|
-
|
28
32
|
match(/^#\s*(.*)$/)
|
29
33
|
end
|
30
34
|
|
35
|
+
##
|
36
|
+
# @return [URI, nil]
|
37
|
+
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (uriref)
|
31
38
|
def read_uriref
|
32
|
-
# <http://www.w3.org/TR/rdf-testcases/#ntrip_grammar> (uriref)
|
33
|
-
|
34
39
|
if uri = match(/^<([^>]+)>/)
|
35
40
|
RDF::URI.parse(uri)
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
44
|
+
##
|
45
|
+
# @return [Node, nil]
|
46
|
+
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (nodeID)
|
39
47
|
def read_bnode
|
40
|
-
# <http://www.w3.org/TR/rdf-testcases/#ntrip_grammar> (nodeID)
|
41
|
-
|
42
48
|
if node_id = match(/^_:([A-Za-z][A-Za-z0-9]*)/)
|
43
49
|
@nodes[node_id] ||= Object.new # TODO: RDF::Node.new
|
44
50
|
end
|
45
51
|
end
|
46
52
|
|
53
|
+
##
|
54
|
+
# @return [String, Literal, nil]
|
55
|
+
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (literal)
|
47
56
|
def read_literal
|
48
|
-
# <http://www.w3.org/TR/rdf-testcases/#ntrip_grammar> (literal)
|
49
|
-
|
50
57
|
if literal = match(/^"((?:\\"|[^"])*)"/)
|
51
58
|
literal = unescaped(literal)
|
52
59
|
|
@@ -62,15 +69,16 @@ module RDF class Reader
|
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
72
|
+
##
|
73
|
+
# @param [String] string
|
74
|
+
# @return [String]
|
75
|
+
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_strings
|
65
76
|
def unescaped(string)
|
66
|
-
# <http://www.w3.org/TR/rdf-testcases/#ntrip_strings>
|
67
|
-
|
68
77
|
["\t", "\n", "\r", "\"", "\\"].each do |escape|
|
69
78
|
string.gsub!(escape.inspect[1...-1], escape)
|
70
79
|
end
|
71
80
|
string.gsub!(/\\u([0-9A-Fa-f]{4,4})/u) { [$1.hex].pack('U*') }
|
72
81
|
string.gsub!(/\\U([0-9A-Fa-f]{8,8})/u) { [$1.hex].pack('U*') }
|
73
|
-
|
74
82
|
string
|
75
83
|
end
|
76
84
|
|
data/lib/rdf/resource.rb
ADDED
data/lib/rdf/statement.rb
CHANGED
@@ -1,30 +1,77 @@
|
|
1
1
|
module RDF
|
2
2
|
##
|
3
3
|
# An RDF statement.
|
4
|
-
class Statement
|
4
|
+
class Statement < Value
|
5
|
+
# @return [Object]
|
6
|
+
attr_accessor :id
|
7
|
+
|
8
|
+
# @return [Resource]
|
5
9
|
attr_accessor :context
|
10
|
+
|
11
|
+
# @return [Resource]
|
6
12
|
attr_accessor :subject
|
13
|
+
|
14
|
+
# @return [URI]
|
7
15
|
attr_accessor :predicate
|
16
|
+
|
17
|
+
# @return [Value]
|
8
18
|
attr_accessor :object
|
9
19
|
|
20
|
+
##
|
21
|
+
# @param [Resource] s
|
22
|
+
# @param [URI] p
|
23
|
+
# @param [Value] o
|
24
|
+
# @option options [Resource] :context (nil)
|
10
25
|
def initialize(s = nil, p = nil, o = nil, options = {})
|
11
26
|
@context = options[:context] || options[:graph]
|
12
27
|
@subject, @predicate, @object = s, p, o
|
13
28
|
end
|
14
29
|
|
30
|
+
##
|
31
|
+
# @return [Boolean]
|
15
32
|
def asserted?() !quoted? end
|
33
|
+
|
34
|
+
##
|
35
|
+
# @return [Boolean]
|
16
36
|
def quoted?() false end
|
17
37
|
|
38
|
+
##
|
39
|
+
# @return [Boolean]
|
18
40
|
def has_graph?() has_context? end
|
41
|
+
|
42
|
+
##
|
43
|
+
# @return [Boolean]
|
19
44
|
def has_context?() !!context end
|
45
|
+
|
46
|
+
##
|
47
|
+
# @return [Boolean]
|
20
48
|
def has_subject?() !!subject end
|
49
|
+
|
50
|
+
##
|
51
|
+
# @return [Boolean]
|
21
52
|
def has_predicate?() !!predicate end
|
53
|
+
|
54
|
+
##
|
55
|
+
# @return [Boolean]
|
22
56
|
def has_object?() !!object end
|
23
57
|
|
58
|
+
##
|
59
|
+
# @param [Statement] other
|
60
|
+
# @return [Boolean]
|
61
|
+
def eql?(other)
|
62
|
+
other.is_a?(Statement) && self == other
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# @param [Object] other
|
67
|
+
# @return [Boolean]
|
24
68
|
def ==(other)
|
25
69
|
to_a == other.to_a
|
26
70
|
end
|
27
71
|
|
72
|
+
##
|
73
|
+
# @param [Statement] other
|
74
|
+
# @return [Boolean]
|
28
75
|
def ===(other)
|
29
76
|
return false if has_subject? && subject != other.subject
|
30
77
|
return false if has_predicate? && predicate != other.predicate
|
@@ -32,10 +79,17 @@ module RDF
|
|
32
79
|
return true
|
33
80
|
end
|
34
81
|
|
82
|
+
##
|
83
|
+
# @param [Integer] index
|
84
|
+
# @return [Value]
|
35
85
|
def [](index)
|
36
86
|
to_a[index]
|
37
87
|
end
|
38
88
|
|
89
|
+
##
|
90
|
+
# @param [Integer] index
|
91
|
+
# @param [Value] value
|
92
|
+
# @return [Value]
|
39
93
|
def []=(index, value)
|
40
94
|
case index
|
41
95
|
when 0 then subject = value
|
@@ -45,16 +99,34 @@ module RDF
|
|
45
99
|
end
|
46
100
|
end
|
47
101
|
|
48
|
-
|
49
|
-
|
50
|
-
def
|
102
|
+
##
|
103
|
+
# @return [Array]
|
104
|
+
def to_triple
|
51
105
|
[subject, predicate, object]
|
52
106
|
end
|
53
107
|
|
108
|
+
##
|
109
|
+
# @return [Array]
|
110
|
+
def to_quad
|
111
|
+
[subject, predicate, object, context]
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# @return [Array]
|
116
|
+
def to_a() to_triple end
|
117
|
+
|
118
|
+
##
|
119
|
+
# @return [Array]
|
120
|
+
def to_ary() to_triple end
|
121
|
+
|
122
|
+
##
|
123
|
+
# @return [Hash]
|
54
124
|
def to_hash
|
55
125
|
{ subject => { predicate => object } }
|
56
126
|
end
|
57
127
|
|
128
|
+
##
|
129
|
+
# @return [String]
|
58
130
|
def to_s
|
59
131
|
require 'stringio' unless defined?(StringIO)
|
60
132
|
StringIO.open do |buffer|
|
@@ -64,9 +136,5 @@ module RDF
|
|
64
136
|
buffer.string
|
65
137
|
end
|
66
138
|
end
|
67
|
-
|
68
|
-
def inspect
|
69
|
-
sprintf("#<%s:%#0x(%s)>", self.class.name, object_id, to_s)
|
70
|
-
end
|
71
139
|
end
|
72
140
|
end
|