rdf-trig 0.0.1
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/AUTHORS +1 -0
- data/History +2 -0
- data/README.markdown +103 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/lib/rdf/trig.rb +33 -0
- data/lib/rdf/trig/format.rb +53 -0
- data/lib/rdf/trig/meta.rb +2427 -0
- data/lib/rdf/trig/reader.rb +118 -0
- data/lib/rdf/trig/version.rb +18 -0
- data/lib/rdf/trig/writer.rb +190 -0
- metadata +221 -0
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'rdf/trig/meta'
|
2
|
+
require 'rdf/turtle'
|
3
|
+
|
4
|
+
module RDF::TriG
|
5
|
+
##
|
6
|
+
# A parser for the TriG
|
7
|
+
#
|
8
|
+
# Leverages the Turtle reader
|
9
|
+
class Reader < RDF::Turtle::Reader
|
10
|
+
format Format
|
11
|
+
include RDF::TriG::Meta
|
12
|
+
|
13
|
+
# String terminals
|
14
|
+
terminal(nil, %r([\{\}\(\),.;\[\]a]|\^\^|@base|@prefix|true|false)) do |reader, prod, token, input|
|
15
|
+
case token.value
|
16
|
+
when 'a' then input[:resource] = RDF.type
|
17
|
+
when 'true', 'false' then input[:resource] = RDF::Literal::Boolean.new(token.value)
|
18
|
+
else input[:string] = token.value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
terminal(:LANGTAG, LANGTAG) do |reader, prod, token, input|
|
22
|
+
input[:lang] = token.value[1..-1]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Productions
|
26
|
+
# [3g] graph defines the basic creation of context
|
27
|
+
production(:graph) do |reader, phase, input, current, callback|
|
28
|
+
current[:context] = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# [4g] graphIri
|
32
|
+
# Normally, just returns the IRIref, but if called from [3g], also
|
33
|
+
# sets the context for triples defined within that graph
|
34
|
+
production(:graphIri) do |reader, phase, input, current, callback|
|
35
|
+
# If input contains set_graph_iri, use the returned value to set @context
|
36
|
+
if phase == :finish
|
37
|
+
callback.call(:trace, "graphIri", lambda {"Set graph context to #{current[:resource]}"})
|
38
|
+
input[:context] = current[:resource]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# [12] object ::= IRIref | blank | literal
|
43
|
+
production(:object) do |reader, phase, input, current, callback|
|
44
|
+
next unless phase == :finish
|
45
|
+
if input[:object_list]
|
46
|
+
# Part of an rdf:List collection
|
47
|
+
input[:object_list] << current[:resource]
|
48
|
+
else
|
49
|
+
callback.call(:trace, "object", lambda {"current: #{current.inspect}"})
|
50
|
+
callback.call(:statement, "object", input[:subject], input[:predicate], current[:resource], input[:context])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# [16] collection ::= "(" object* ")"
|
55
|
+
production(:collection) do |reader, phase, input, current, callback|
|
56
|
+
if phase == :start
|
57
|
+
current[:object_list] = [] # Tells the object production to collect and not generate statements
|
58
|
+
else
|
59
|
+
# Create an RDF list
|
60
|
+
bnode = reader.bnode
|
61
|
+
objects = current[:object_list]
|
62
|
+
list = RDF::List.new(bnode, nil, objects)
|
63
|
+
list.each_statement do |statement|
|
64
|
+
# Spec Confusion, referenced section "Collection" is missing from the spec.
|
65
|
+
# Anicdodal evidence indicates that some expect each node to be of type rdf:list,
|
66
|
+
# but existing Notation3 and Turtle tests (http://www.w3.org/2001/sw/DataAccess/df1/tests/manifest.ttl) do not.
|
67
|
+
next if statement.predicate == RDF.type && statement.object == RDF.List
|
68
|
+
callback.call(:statement, "collection", statement.subject, statement.predicate, statement.object, input[:context])
|
69
|
+
end
|
70
|
+
bnode = RDF.nil if list.empty?
|
71
|
+
|
72
|
+
# Return bnode as resource
|
73
|
+
input[:resource] = bnode
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Iterates the given block for each RDF statement in the input.
|
79
|
+
#
|
80
|
+
# @yield [statement]
|
81
|
+
# @yieldparam [RDF::Statement] statement
|
82
|
+
# @return [void]
|
83
|
+
def each_statement(&block)
|
84
|
+
@callback = block
|
85
|
+
|
86
|
+
parse(@input, START.to_sym, @options.merge(:branch => BRANCH,
|
87
|
+
:first => FIRST,
|
88
|
+
:follow => FOLLOW)
|
89
|
+
) do |context, *data|
|
90
|
+
loc = data.shift
|
91
|
+
case context
|
92
|
+
when :statement
|
93
|
+
add_statement(loc, RDF::Statement.from(data))
|
94
|
+
when :trace
|
95
|
+
debug(loc, *data)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
rescue RDF::LL1::Parser::Error => e
|
99
|
+
debug("Parsing completed with errors:\n\t#{e.message}")
|
100
|
+
raise RDF::ReaderError, e.message if validate?
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Iterates the given block for each RDF quad in the input.
|
105
|
+
#
|
106
|
+
# @yield [subject, predicate, object, context]
|
107
|
+
# @yieldparam [RDF::Resource] subject
|
108
|
+
# @yieldparam [RDF::URI] predicate
|
109
|
+
# @yieldparam [RDF::Value] object
|
110
|
+
# @yieldparam [RDF::URI] context
|
111
|
+
# @return [void]
|
112
|
+
def each_quad(&block)
|
113
|
+
each_statement do |statement|
|
114
|
+
block.call(*statement.to_quad)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end # class Reader
|
118
|
+
end # module RDF::Turtle
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RDF::TriG::VERSION
|
2
|
+
VERSION_FILE = File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "VERSION")
|
3
|
+
MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chop.split(".")
|
4
|
+
|
5
|
+
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
|
6
|
+
|
7
|
+
##
|
8
|
+
# @return [String]
|
9
|
+
def self.to_s() STRING end
|
10
|
+
|
11
|
+
##
|
12
|
+
# @return [String]
|
13
|
+
def self.to_str() STRING end
|
14
|
+
|
15
|
+
##
|
16
|
+
# @return [Array(Integer, Integer, Integer)]
|
17
|
+
def self.to_a() STRING.split(".") end
|
18
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'rdf/turtle'
|
2
|
+
|
3
|
+
module RDF::TriG
|
4
|
+
##
|
5
|
+
# A TriG serialiser
|
6
|
+
#
|
7
|
+
# Note that the natural interface is to write a whole repository at a time.
|
8
|
+
# Writing statements or Triples will create a repository to add them to
|
9
|
+
# and then serialize the repository.
|
10
|
+
#
|
11
|
+
# @example Obtaining a TriG writer class
|
12
|
+
# RDF::Writer.for(:trig) #=> RDF::TriG::Writer
|
13
|
+
# RDF::Writer.for("etc/test.trig")
|
14
|
+
# RDF::Writer.for(:file_name => "etc/test.trig")
|
15
|
+
# RDF::Writer.for(:file_extension => "trig")
|
16
|
+
# RDF::Writer.for(:content_type => "application/trig")
|
17
|
+
#
|
18
|
+
# @example Serializing RDF repo into an TriG file
|
19
|
+
# RDF::TriG::Writer.open("etc/test.trig") do |writer|
|
20
|
+
# writer << repo
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @example Serializing RDF statements into an TriG file
|
24
|
+
# RDF::TriG::Writer.open("etc/test.trig") do |writer|
|
25
|
+
# repo.each_statement do |statement|
|
26
|
+
# writer << statement
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @example Serializing RDF statements into an TriG string
|
31
|
+
# RDF::TriG::Writer.buffer do |writer|
|
32
|
+
# repo.each_statement do |statement|
|
33
|
+
# writer << statement
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# The writer will add prefix definitions, and use them for creating @prefix definitions, and minting QNames
|
38
|
+
#
|
39
|
+
# @example Creating @base and @prefix definitions in output
|
40
|
+
# RDF::TriG::Writer.buffer(:base_uri => "http://example.com/", :prefixes => {
|
41
|
+
# nil => "http://example.com/ns#",
|
42
|
+
# :foaf => "http://xmlns.com/foaf/0.1/"}
|
43
|
+
# ) do |writer|
|
44
|
+
# repo.each_statement do |statement|
|
45
|
+
# writer << statement
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# @author [Gregg Kellogg](http://kellogg-assoc.com/)
|
50
|
+
class Writer < RDF::Turtle::Writer
|
51
|
+
format RDF::TriG::Format
|
52
|
+
|
53
|
+
class ContextFilteredRepo
|
54
|
+
include RDF::Queryable
|
55
|
+
|
56
|
+
def initialize(repo, context)
|
57
|
+
@repo = repo
|
58
|
+
@context = context
|
59
|
+
end
|
60
|
+
|
61
|
+
# Filter statements in repository to those having the specified context
|
62
|
+
# Returns each statement having the specified context, `false` for default context
|
63
|
+
# @yield statement
|
64
|
+
# @yieldparam [RDF::Statement] statement
|
65
|
+
# @return [void]
|
66
|
+
# @see [RDF::Queryable]
|
67
|
+
def each
|
68
|
+
@repo.each_statement do |st|
|
69
|
+
case @context
|
70
|
+
when false
|
71
|
+
yield st if !st.context
|
72
|
+
else
|
73
|
+
yield st if st.context == @context
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Proxy Repository#query_pattern
|
80
|
+
# @see RDF::Repository#query_pattern
|
81
|
+
def query_pattern(pattern, &block)
|
82
|
+
pattern.context = @context || false
|
83
|
+
@repo.send(:query_pattern, pattern, &block)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Initializes the TriG writer instance.
|
89
|
+
#
|
90
|
+
# @param [IO, File] output
|
91
|
+
# the output stream
|
92
|
+
# @param [Hash{Symbol => Object}] options
|
93
|
+
# any additional options
|
94
|
+
# @option options [Encoding] :encoding (Encoding::UTF_8)
|
95
|
+
# the encoding to use on the output stream (Ruby 1.9+)
|
96
|
+
# @option options [Boolean] :canonicalize (false)
|
97
|
+
# whether to canonicalize literals when serializing
|
98
|
+
# @option options [Hash] :prefixes (Hash.new)
|
99
|
+
# the prefix mappings to use (not supported by all writers)
|
100
|
+
# @option options [#to_s] :base_uri (nil)
|
101
|
+
# the base URI to use when constructing relative URIs
|
102
|
+
# @option options [Integer] :max_depth (3)
|
103
|
+
# Maximum depth for recursively defining resources, defaults to 3
|
104
|
+
# @option options [Boolean] :standard_prefixes (false)
|
105
|
+
# Add standard prefixes to @prefixes, if necessary.
|
106
|
+
# @option options [String] :default_namespace (nil)
|
107
|
+
# URI to use as default namespace, same as prefixes[nil]
|
108
|
+
# @yield [writer] `self`
|
109
|
+
# @yieldparam [RDF::Writer] writer
|
110
|
+
# @yieldreturn [void]
|
111
|
+
# @yield [writer]
|
112
|
+
# @yieldparam [RDF::Writer] writer
|
113
|
+
def initialize(output = $stdout, options = {}, &block)
|
114
|
+
super do
|
115
|
+
# Set both @repo and @graph to a new repository.
|
116
|
+
# When serializing a context, @graph is changed
|
117
|
+
# to a ContextFilteredRepo
|
118
|
+
@repo = @graph = RDF::Repository.new
|
119
|
+
if block_given?
|
120
|
+
case block.arity
|
121
|
+
when 0 then instance_eval(&block)
|
122
|
+
else block.call(self)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Outputs the TriG representation of all stored triples.
|
130
|
+
#
|
131
|
+
# @return [void]
|
132
|
+
# @see #write_triple
|
133
|
+
def write_epilogue
|
134
|
+
@max_depth = @options[:max_depth] || 3
|
135
|
+
@base_uri = RDF::URI(@options[:base_uri])
|
136
|
+
|
137
|
+
reset
|
138
|
+
|
139
|
+
debug {"\nserialize: repo: #{@repo.size}"}
|
140
|
+
|
141
|
+
preprocess
|
142
|
+
start_document
|
143
|
+
|
144
|
+
order_contexts.each do |ctx|
|
145
|
+
debug {"context: #{ctx.inspect}"}
|
146
|
+
reset
|
147
|
+
@depth = 2
|
148
|
+
|
149
|
+
if ctx
|
150
|
+
@output.write("\n#{format_value(ctx)} {")
|
151
|
+
else
|
152
|
+
@output.write("\n{")
|
153
|
+
end
|
154
|
+
|
155
|
+
# Restrict view to the particular context
|
156
|
+
@graph = ContextFilteredRepo.new(@repo, ctx)
|
157
|
+
|
158
|
+
# Pre-process statements again, but in the specified context
|
159
|
+
@graph.each {|st| preprocess_statement(st)}
|
160
|
+
order_subjects.each do |subject|
|
161
|
+
unless is_done?(subject)
|
162
|
+
statement(subject)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
@output.puts("}")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
protected
|
171
|
+
# Order contexts for output
|
172
|
+
def order_contexts
|
173
|
+
debug("order_contexts") {repo.contexts.to_a.inspect}
|
174
|
+
contexts = repo.contexts.to_a.sort
|
175
|
+
|
176
|
+
# include default context, if necessary
|
177
|
+
contexts.unshift(nil) unless repo.query(:context => false).to_a.empty?
|
178
|
+
|
179
|
+
contexts
|
180
|
+
end
|
181
|
+
|
182
|
+
# Perform any statement preprocessing required. This is used to perform reference counts and determine required
|
183
|
+
# prefixes.
|
184
|
+
# @param [Statement] statement
|
185
|
+
def preprocess_statement(statement)
|
186
|
+
super
|
187
|
+
get_pname(statement.context) if statement.has_context?
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
metadata
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rdf-trig
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Gregg Kellogg
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-12-22 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rdf
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 27
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 3
|
32
|
+
- 4
|
33
|
+
version: 0.3.4
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rdf-turtle
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 25
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 1
|
48
|
+
- 1
|
49
|
+
version: 0.1.1
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: open-uri-cached
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 23
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
- 0
|
64
|
+
- 4
|
65
|
+
version: 0.0.4
|
66
|
+
type: :development
|
67
|
+
version_requirements: *id003
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: spira
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 7
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
- 0
|
80
|
+
- 12
|
81
|
+
version: 0.0.12
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id004
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rspec
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
hash: 27
|
93
|
+
segments:
|
94
|
+
- 2
|
95
|
+
- 5
|
96
|
+
- 0
|
97
|
+
version: 2.5.0
|
98
|
+
type: :development
|
99
|
+
version_requirements: *id005
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: rdf-isomorphic
|
102
|
+
prerelease: false
|
103
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 27
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
- 3
|
112
|
+
- 4
|
113
|
+
version: 0.3.4
|
114
|
+
type: :development
|
115
|
+
version_requirements: *id006
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: rdf-n3
|
118
|
+
prerelease: false
|
119
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
hash: 25
|
125
|
+
segments:
|
126
|
+
- 0
|
127
|
+
- 3
|
128
|
+
- 5
|
129
|
+
version: 0.3.5
|
130
|
+
type: :development
|
131
|
+
version_requirements: *id007
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
name: rdf-spec
|
134
|
+
prerelease: false
|
135
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
hash: 27
|
141
|
+
segments:
|
142
|
+
- 0
|
143
|
+
- 3
|
144
|
+
- 4
|
145
|
+
version: 0.3.4
|
146
|
+
type: :development
|
147
|
+
version_requirements: *id008
|
148
|
+
- !ruby/object:Gem::Dependency
|
149
|
+
name: yard
|
150
|
+
prerelease: false
|
151
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
hash: 7
|
157
|
+
segments:
|
158
|
+
- 0
|
159
|
+
- 6
|
160
|
+
- 0
|
161
|
+
version: 0.6.0
|
162
|
+
type: :development
|
163
|
+
version_requirements: *id009
|
164
|
+
description: RDF::TriG is an TriG reader/writer for the RDF.rb library suite.
|
165
|
+
email: public-rdf-ruby@w3.org
|
166
|
+
executables: []
|
167
|
+
|
168
|
+
extensions: []
|
169
|
+
|
170
|
+
extra_rdoc_files: []
|
171
|
+
|
172
|
+
files:
|
173
|
+
- AUTHORS
|
174
|
+
- README.markdown
|
175
|
+
- History
|
176
|
+
- UNLICENSE
|
177
|
+
- VERSION
|
178
|
+
- lib/rdf/trig/format.rb
|
179
|
+
- lib/rdf/trig/meta.rb
|
180
|
+
- lib/rdf/trig/reader.rb
|
181
|
+
- lib/rdf/trig/version.rb
|
182
|
+
- lib/rdf/trig/writer.rb
|
183
|
+
- lib/rdf/trig.rb
|
184
|
+
homepage: http://github.com/gkellogg/rdf-trig
|
185
|
+
licenses:
|
186
|
+
- Public Domain
|
187
|
+
post_install_message:
|
188
|
+
rdoc_options: []
|
189
|
+
|
190
|
+
require_paths:
|
191
|
+
- lib
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
194
|
+
requirements:
|
195
|
+
- - ">="
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
hash: 53
|
198
|
+
segments:
|
199
|
+
- 1
|
200
|
+
- 8
|
201
|
+
- 1
|
202
|
+
version: 1.8.1
|
203
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
204
|
+
none: false
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
hash: 3
|
209
|
+
segments:
|
210
|
+
- 0
|
211
|
+
version: "0"
|
212
|
+
requirements: []
|
213
|
+
|
214
|
+
rubyforge_project: rdf-trig
|
215
|
+
rubygems_version: 1.8.10
|
216
|
+
signing_key:
|
217
|
+
specification_version: 3
|
218
|
+
summary: TriG reader/writer for Ruby.
|
219
|
+
test_files: []
|
220
|
+
|
221
|
+
has_rdoc: false
|