rdf-rdfxml 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +10 -0
- data/AUTHORS +1 -0
- data/History.txt +2 -0
- data/README.rdoc +61 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/example.rb +38 -0
- data/lib/rdf/rdfxml.rb +28 -0
- data/lib/rdf/rdfxml/format.rb +29 -0
- data/lib/rdf/rdfxml/reader.rb +583 -0
- data/lib/rdf/rdfxml/version.rb +21 -0
- data/lib/rdf/rdfxml/writer.rb +0 -0
- metadata +155 -0
data/.yardopts
ADDED
data/AUTHORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Gregg Kellogg <gregg@kellogg-assoc.com>
|
data/History.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
= RDF::RDFa reader/writer
|
2
|
+
|
3
|
+
RDF/XML parser for RDF.rb.
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
RDF::RDFXML is an RDF/XML parser for Ruby using the RDF.rb library suite.
|
8
|
+
|
9
|
+
== FEATURES:
|
10
|
+
RDF::RDFXML parses RDF/XML into statements or triples.
|
11
|
+
|
12
|
+
* Fully compliant RDF/XML parser.
|
13
|
+
|
14
|
+
Install with 'gem install rdf-rdfxml'
|
15
|
+
|
16
|
+
== Usage:
|
17
|
+
Instantiate a parser and parse source, specifying type and base-URL
|
18
|
+
|
19
|
+
RDF::RDFXML::Reader.open("etc/foaf.xml") do |reader|
|
20
|
+
reader.each_statement do |statement|
|
21
|
+
puts statement.inspect
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
== Resources:
|
26
|
+
* Distiller[http://kellogg-assoc/distiller]
|
27
|
+
* RDoc[http://rdoc.info/projects/gkellogg/rdf-rdfxml]
|
28
|
+
* History[http://github.com/gkellogg/rdf-rdfxml/blob/master/History.txt]
|
29
|
+
|
30
|
+
== LICENSE:
|
31
|
+
|
32
|
+
(The MIT License)
|
33
|
+
|
34
|
+
Copyright (c) 2009-2010 Gregg Kellogg
|
35
|
+
|
36
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
37
|
+
a copy of this software and associated documentation files (the
|
38
|
+
'Software'), to deal in the Software without restriction, including
|
39
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
40
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
41
|
+
permit persons to whom the Software is furnished to do so, subject to
|
42
|
+
the following conditions:
|
43
|
+
|
44
|
+
The above copyright notice and this permission notice shall be
|
45
|
+
included in all copies or substantial portions of the Software.
|
46
|
+
|
47
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
48
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
49
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
50
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
51
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
52
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
53
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
54
|
+
|
55
|
+
== FEEDBACK
|
56
|
+
|
57
|
+
* gregg@kellogg-assoc.com
|
58
|
+
* rubygems.org/rdf-rdfxml
|
59
|
+
* github.com/gkellogg/rdf-rdfxml
|
60
|
+
* gkellogg.lighthouseapp.com for bug reports
|
61
|
+
* public-rdf-ruby mailing list on w3.org
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
begin
|
4
|
+
gem 'jeweler'
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
gemspec.name = "rdf-rdfxml"
|
8
|
+
gemspec.summary = "RDF/XML reader/writer for RDF.rb."
|
9
|
+
gemspec.description = <<-DESCRIPTION
|
10
|
+
RDF::RDFXML is an RDF/XML reader and writer for Ruby using the RDF.rb library suite.
|
11
|
+
DESCRIPTION
|
12
|
+
gemspec.email = "gregg@kellogg-assoc.com"
|
13
|
+
gemspec.homepage = "http://github.com/gkellogg/rdf-rdfxml"
|
14
|
+
gemspec.authors = ["Gregg Kellogg"]
|
15
|
+
gemspec.add_dependency('rdf', '>= 0.1.6')
|
16
|
+
gemspec.add_dependency('nokogiri', '>= 1.3.3')
|
17
|
+
gemspec.add_development_dependency('rspec')
|
18
|
+
gemspec.add_development_dependency('rdf-spec')
|
19
|
+
gemspec.add_development_dependency('activesupport', '>= 2.3.0')
|
20
|
+
gemspec.extra_rdoc_files = %w(README.rdoc History.txt AUTHORS)
|
21
|
+
end
|
22
|
+
Jeweler::GemcutterTasks.new
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'spec/rake/spectask'
|
28
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
30
|
+
spec.spec_files = FileList['spec/*_spec.rb']
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Run specs through RCov"
|
34
|
+
Spec::Rake::SpecTask.new("spec:rcov") do |spec|
|
35
|
+
spec.libs << 'lib' << 'spec'
|
36
|
+
spec.pattern = 'spec/*_spec.rb'
|
37
|
+
spec.rcov = true
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Generate HTML report specs"
|
41
|
+
Spec::Rake::SpecTask.new("doc:spec") do |spec|
|
42
|
+
spec.libs << 'lib' << 'spec'
|
43
|
+
spec.spec_files = FileList['spec/*_spec.rb']
|
44
|
+
spec.spec_opts = ["--format", "html:doc/spec.html"]
|
45
|
+
end
|
46
|
+
|
47
|
+
task :default => :spec
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/example.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'rdf/rdfxml'
|
7
|
+
|
8
|
+
data = <<-EOF;
|
9
|
+
<?xml version="1.0" ?>
|
10
|
+
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
11
|
+
xmlns:ex="http://www.example.org/" xml:lang="en" xml:base="http://www.example.org/foo">
|
12
|
+
<ex:Thing rdf:about="http://example.org/joe" ex:name="bar">
|
13
|
+
<ex:belongsTo rdf:resource="http://tommorris.org/" />
|
14
|
+
<ex:sampleText rdf:datatype="http://www.w3.org/2001/XMLSchema#string">foo</ex:sampleText>
|
15
|
+
<ex:hadADodgyRelationshipWith>
|
16
|
+
<rdf:Description>
|
17
|
+
<ex:name>Tom</ex:name>
|
18
|
+
<ex:hadADodgyRelationshipWith>
|
19
|
+
<rdf:Description>
|
20
|
+
<ex:name>Rob</ex:name>
|
21
|
+
<ex:hadADodgyRelationshipWith>
|
22
|
+
<rdf:Description>
|
23
|
+
<ex:name>Mary</ex:name>
|
24
|
+
</rdf:Description>
|
25
|
+
</ex:hadADodgyRelationshipWith>
|
26
|
+
</rdf:Description>
|
27
|
+
</ex:hadADodgyRelationshipWith>
|
28
|
+
</rdf:Description>
|
29
|
+
</ex:hadADodgyRelationshipWith>
|
30
|
+
</ex:Thing>
|
31
|
+
</rdf:RDF>
|
32
|
+
EOF
|
33
|
+
|
34
|
+
RDF::RDFXML::Reader.new(data, :base_uri => 'http://example.org/example.xml') do |reader|
|
35
|
+
reader.each_statement do |statement|
|
36
|
+
statement.inspect!
|
37
|
+
end
|
38
|
+
end
|
data/lib/rdf/rdfxml.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
2
|
+
require 'rdf'
|
3
|
+
|
4
|
+
module RDF
|
5
|
+
##
|
6
|
+
# **`RDF::RDFXML`** is an RDF/XML plugin for RDF.rb.
|
7
|
+
#
|
8
|
+
# @example Requiring the `RDF::RDFXML` module
|
9
|
+
# require 'rdf/rdfxml'
|
10
|
+
#
|
11
|
+
# @example Parsing RDF statements from an XHTML+RDFa file
|
12
|
+
# RDF::RDFXML::Reader.open("etc/foaf.xml") do |reader|
|
13
|
+
# reader.each_statement do |statement|
|
14
|
+
# puts statement.inspect
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# @see http://rdf.rubyforge.org/
|
19
|
+
# @see http://www.w3.org/TR/REC-rdf-syntax/
|
20
|
+
#
|
21
|
+
# @author [Gregg Kellogg](http://kellogg-assoc.com/)
|
22
|
+
module RDFa
|
23
|
+
require 'rdfxml/format'
|
24
|
+
require 'rdfxml/vocab'
|
25
|
+
autoload :Reader, 'rdf/rdfxml/reader'
|
26
|
+
autoload :VERSION, 'rdf/rdfxml/version'
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RDF::RDFXML
|
2
|
+
##
|
3
|
+
# RDFa format specification.
|
4
|
+
#
|
5
|
+
# @example Obtaining an RDFa format class
|
6
|
+
# RDF::Format.for(:rdfxml) #=> RDF::RDFXML::Format
|
7
|
+
# RDF::Format.for("etc/foaf.xml")
|
8
|
+
# RDF::Format.for(:file_name => "etc/foaf.xml")
|
9
|
+
# RDF::Format.for(:file_extension => "xml")
|
10
|
+
# RDF::Format.for(:file_extension => "rdf")
|
11
|
+
# RDF::Format.for(:content_type => "application/xml")
|
12
|
+
# RDF::Format.for(:content_type => "application/rdf+xml")
|
13
|
+
#
|
14
|
+
# @example Obtaining serialization format MIME types
|
15
|
+
# RDF::Format.content_types #=> {"application/rdf+xml" => [RDF::RDFXML::Format]}
|
16
|
+
#
|
17
|
+
# @example Obtaining serialization format file extension mappings
|
18
|
+
# RDF::Format.file_extensions #=> {:rdf => "application/rdf+xml"}
|
19
|
+
#
|
20
|
+
# @see http://www.w3.org/TR/rdf-testcases/#ntriples
|
21
|
+
class Format < RDF::Format
|
22
|
+
content_type 'application/xml', :extension => :xml
|
23
|
+
content_type 'application/rdf+xml', :extension => :rdf
|
24
|
+
content_encoding 'utf-8'
|
25
|
+
|
26
|
+
reader { RDF::RDFa::RDFXML }
|
27
|
+
writer { RDF::RDFa::RDFXML }
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,583 @@
|
|
1
|
+
require 'nokogiri' # FIXME: Implement using different modules as in RDF::TriX
|
2
|
+
|
3
|
+
module RDF::RDFXML
|
4
|
+
##
|
5
|
+
# An RDF/XML parser in Ruby
|
6
|
+
#
|
7
|
+
# @author [Gregg Kellogg](http://kellogg-assoc.com/)
|
8
|
+
class Reader < RDF::Reader
|
9
|
+
format Format
|
10
|
+
|
11
|
+
CORE_SYNTAX_TERMS = %w(RDF ID about parseType resource nodeID datatype).map {|n| "http://www.w3.org/1999/02/22-rdf-syntax-ns##{n}"}
|
12
|
+
OLD_TERMS = %w(aboutEach aboutEachPrefix bagID).map {|n| "http://www.w3.org/1999/02/22-rdf-syntax-ns##{n}"}
|
13
|
+
|
14
|
+
NC_REGEXP = Regexp.new(
|
15
|
+
%{^
|
16
|
+
(?!\\\\u0301) # ́ is a non-spacing acute accent.
|
17
|
+
# It is legal within an XML Name, but not as the first character.
|
18
|
+
( [a-zA-Z_]
|
19
|
+
| \\\\u[0-9a-fA-F]
|
20
|
+
)
|
21
|
+
( [0-9a-zA-Z_\.-]
|
22
|
+
| \\\\u([0-9a-fA-F]{4})
|
23
|
+
)*
|
24
|
+
$},
|
25
|
+
Regexp::EXTENDED)
|
26
|
+
|
27
|
+
XML_LITERAL = RDF['XMLLiteral']
|
28
|
+
|
29
|
+
# The Recursive Baggage
|
30
|
+
class EvaluationContext # :nodoc:
|
31
|
+
attr_reader :base
|
32
|
+
attr :subject, true
|
33
|
+
attr :uri_mappings, true
|
34
|
+
attr :language, true
|
35
|
+
attr :graph, true
|
36
|
+
attr :li_counter, true
|
37
|
+
|
38
|
+
def initialize(base, element, graph)
|
39
|
+
# Initialize the evaluation context, [5.1]
|
40
|
+
self.base = RDF::URI.new(base)
|
41
|
+
@uri_mappings = {}
|
42
|
+
@language = nil
|
43
|
+
@graph = graph
|
44
|
+
@li_counter = 0
|
45
|
+
@uri_mappings = {}
|
46
|
+
|
47
|
+
extract_from_element(element) if element
|
48
|
+
end
|
49
|
+
|
50
|
+
# Clone existing evaluation context adding information from element
|
51
|
+
def clone(element, options = {})
|
52
|
+
new_ec = EvaluationContext.new(@base, nil, @graph)
|
53
|
+
new_ec.uri_mappings = self.uri_mappings.clone
|
54
|
+
new_ec.language = self.language
|
55
|
+
|
56
|
+
new_ec.extract_from_element(element) if element
|
57
|
+
|
58
|
+
options.each_pair {|k, v| new_ec.send("#{k}=", v)}
|
59
|
+
new_ec
|
60
|
+
end
|
61
|
+
|
62
|
+
# Extract Evaluation Context from an element by looking at ancestors recurively
|
63
|
+
def extract_from_ancestors(el)
|
64
|
+
ancestors = el.ancestors
|
65
|
+
while ancestors.length > 0
|
66
|
+
a = ancestors.pop
|
67
|
+
next unless a.element?
|
68
|
+
extract_from_element(a)
|
69
|
+
end
|
70
|
+
extract_from_element(el)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Extract Evaluation Context from an element
|
74
|
+
def extract_from_element(el)
|
75
|
+
b = el.attribute_with_ns("base", XML_NS.uri.to_s)
|
76
|
+
lang = el.attribute_with_ns("lang", XML_NS.uri.to_s)
|
77
|
+
self.base = self.base.join(b) if b
|
78
|
+
self.language = lang if lang
|
79
|
+
self.uri_mappings.merge!(extract_mappings(el))
|
80
|
+
end
|
81
|
+
|
82
|
+
# Extract the XMLNS mappings from an element
|
83
|
+
def extract_mappings(element)
|
84
|
+
mappings = {}
|
85
|
+
|
86
|
+
# look for xmlns
|
87
|
+
element.namespaces.each do |attr_name,attr_value|
|
88
|
+
abbr, suffix = attr_name.to_s.split(":")
|
89
|
+
if abbr == "xmlns"
|
90
|
+
attr_value = self.base.to_s + attr_value if attr_value.match(/^\#/)
|
91
|
+
mappings[suffix] = Namespace.new(attr_value, suffix)
|
92
|
+
@graph.bind(mappings[suffix])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
mappings
|
96
|
+
end
|
97
|
+
|
98
|
+
# Produce the next list entry for this context
|
99
|
+
def li_next
|
100
|
+
@li_counter += 1
|
101
|
+
predicate = URIRef.new(RDF["_#{@li_counter}"])
|
102
|
+
end
|
103
|
+
|
104
|
+
# Set XML base. Ignore any fragment
|
105
|
+
def base=(b)
|
106
|
+
b = Addressable::URI.parse(b.to_s)
|
107
|
+
b.fragment = nil
|
108
|
+
@base = RDF::URI.new(b)
|
109
|
+
end
|
110
|
+
|
111
|
+
def inspect
|
112
|
+
v = %w(base subject language).map {|a| "#{a}='#{self.send(a).nil? ? 'nil' : self.send(a)}'"}
|
113
|
+
v << "uri_mappings[#{uri_mappings.keys.length}]"
|
114
|
+
v.join(",")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# Initializes the RDF/XML reader instance.
|
120
|
+
#
|
121
|
+
# @param [IO, File, String]:: input
|
122
|
+
# @param [Hash{Symbol => Object}]:: options
|
123
|
+
# <em>options[:debug]</em>:: Array to place debug messages
|
124
|
+
# <em>options[:strict]</em>:: Raise Error if true, continue with lax parsing, otherwise
|
125
|
+
# <em>options[:base_uri]</em>:: Base URI to use for relative URIs.
|
126
|
+
# @yield [reader]
|
127
|
+
# @yieldparam [Reader] reader
|
128
|
+
# @raise [Error]:: Raises RDF::ReaderError if _strict_
|
129
|
+
def initialize(input = $stdin, options = {}, &block)
|
130
|
+
super do
|
131
|
+
@graph = RDF::Graph.new
|
132
|
+
@debug = options[:debug]
|
133
|
+
@strict = options[:strict]
|
134
|
+
@base_uri = options[:base_uri]
|
135
|
+
@base_uri = RDF::URI.parse(@base_uri) if @base_uri.is_a?(String)
|
136
|
+
|
137
|
+
@doc = case stream
|
138
|
+
when Nokogiri::XML::Document then stream
|
139
|
+
else Nokogiri::XML.parse(stream, uri.to_s)
|
140
|
+
end
|
141
|
+
|
142
|
+
raise RDF::ReaderError, "Empty document" if @doc.nil? && @strict
|
143
|
+
@callback = block
|
144
|
+
|
145
|
+
# Look for rdf:RDF elements and process each.
|
146
|
+
rdf_nodes = root.xpath("//rdf:RDF", RDF.prefix => RDF.uri.to_s)
|
147
|
+
if rdf_nodes.length == 0
|
148
|
+
# If none found, root element may be processed as an RDF Node
|
149
|
+
|
150
|
+
ec = EvaluationContext.new(@uri, root, @graph)
|
151
|
+
nodeElement(root, ec)
|
152
|
+
else
|
153
|
+
rdf_nodes.each do |node|
|
154
|
+
# XXX Skip this element if it's contained within another rdf:RDF element
|
155
|
+
|
156
|
+
# Extract base, lang and namespaces from parents to create proper evaluation context
|
157
|
+
ec = EvaluationContext.new(@uri, nil, @graph)
|
158
|
+
ec.extract_from_ancestors(node)
|
159
|
+
node.children.each {|el|
|
160
|
+
next unless el.elem?
|
161
|
+
new_ec = ec.clone(el)
|
162
|
+
nodeElement(el, new_ec)
|
163
|
+
}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
block.call(self) if block_given?
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
# Figure out the document path, if it is a Nokogiri::XML::Element or Attribute
|
174
|
+
def node_path(node)
|
175
|
+
case node
|
176
|
+
when Nokogiri::XML::Element, Nokogiri::XML::Attr then "#{node_path(node.parent)}/#{node.name}"
|
177
|
+
when String then node
|
178
|
+
else ""
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Add debug event to debug array, if specified
|
183
|
+
#
|
184
|
+
# @param [XML Node, any] node:: XML Node or string for showing context
|
185
|
+
# @param [String] message::
|
186
|
+
def add_debug(node, message)
|
187
|
+
puts "#{node_path(node)}: #{message}" if $DEBUG
|
188
|
+
@debug << "#{node_path(node)}: #{message}" if @debug.is_a?(Array)
|
189
|
+
end
|
190
|
+
|
191
|
+
# add a statement, object can be literal or URI or bnode
|
192
|
+
#
|
193
|
+
# @param [Nokogiri::XML::Node, any] node:: XML Node or string for showing context
|
194
|
+
# @param [URI, BNode] subject:: the subject of the statement
|
195
|
+
# @param [URI] predicate:: the predicate of the statement
|
196
|
+
# @param [URI, BNode, Literal] object:: the object of the statement
|
197
|
+
# @return [Statement]:: Added statement
|
198
|
+
# @raise [RDF::ReaderError]:: Checks parameter types and raises if they are incorrect if parsing mode is _strict_.
|
199
|
+
def add_triple(node, subject, predicate, object)
|
200
|
+
statement = RDF::Statement.new(subject, predicate, object)
|
201
|
+
add_debug(node, "statement: #{statement}")
|
202
|
+
@graph << statement
|
203
|
+
statement
|
204
|
+
rescue RDF::ReaderError => e
|
205
|
+
add_debug(node, "add_triple raised #{e.class}: #{e.message}")
|
206
|
+
puts e.backtrace if $DEBUG
|
207
|
+
raise if @strict
|
208
|
+
end
|
209
|
+
|
210
|
+
# XML nodeElement production
|
211
|
+
#
|
212
|
+
# @param [XML Element] el:: XMl Element to parse
|
213
|
+
# @param [EvaluationContext] ec:: Evaluation context
|
214
|
+
# @return [RDF::URI] subject:: The subject found for the node
|
215
|
+
# @raise [RDF::ReaderError]:: Raises Exception if _strict_
|
216
|
+
def nodeElement(el, ec)
|
217
|
+
# subject
|
218
|
+
subject = ec.subject || parse_subject(el, ec)
|
219
|
+
|
220
|
+
add_debug(el, "nodeElement, ec: #{ec.inspect}")
|
221
|
+
add_debug(el, "nodeElement, el: #{el.uri}")
|
222
|
+
add_debug(el, "nodeElement, subject: #{subject.nil? ? 'nil' : subject.to_s}")
|
223
|
+
|
224
|
+
unless el.uri == RDF.Description.to_s
|
225
|
+
add_triple(el, subject, RDF.type, el.uri)
|
226
|
+
end
|
227
|
+
|
228
|
+
# produce triples for attributes
|
229
|
+
el.attribute_nodes.each do |attr|
|
230
|
+
add_debug(el, "propertyAttr: #{attr.uri}='#{attr.value}'")
|
231
|
+
if attr.uri == RDF.type
|
232
|
+
# If there is an attribute a in propertyAttr with a.URI == rdf:type
|
233
|
+
# then u:=uri(identifier:=resolve(a.string-value))
|
234
|
+
# and the following triple is added to the graph:
|
235
|
+
u = ec.base.join(attr.value)
|
236
|
+
add_triple(attr, subject, RDF.type, u)
|
237
|
+
elsif is_propertyAttr?(attr)
|
238
|
+
# Attributes not RDF.type
|
239
|
+
predicate = attr.uri
|
240
|
+
lit = Literal.untyped(attr.value, ec.language)
|
241
|
+
add_triple(attr, subject, predicate, lit)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Handle the propertyEltList children events in document order
|
246
|
+
li_counter = 0 # this will increase for each li we iterate through
|
247
|
+
el.children.each do |child|
|
248
|
+
next unless child.elem?
|
249
|
+
child_ec = ec.clone(child)
|
250
|
+
predicate = child.uri
|
251
|
+
add_debug(child, "propertyElt, predicate: #{predicate}")
|
252
|
+
propertyElementURI_check(child)
|
253
|
+
|
254
|
+
# Determine the content type of this property element
|
255
|
+
text_nodes = child.children.select {|e| e.text? && !e.blank?}
|
256
|
+
element_nodes = child.children.select {|c| c.element? }
|
257
|
+
add_debug(child, "#{text_nodes.length} text nodes, #{element_nodes.length} element nodes")
|
258
|
+
if element_nodes.length > 1
|
259
|
+
element_nodes.each do |node|
|
260
|
+
add_debug(child, " node: #{node.to_s}")
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# List expansion
|
265
|
+
predicate = ec.li_next if predicate == RDF.li
|
266
|
+
|
267
|
+
# Productions based on set of attributes
|
268
|
+
|
269
|
+
# All remaining reserved XML Names (See Name in XML 1.0) are now removed from the set.
|
270
|
+
# These are, all attribute information items in the set with property [prefix] beginning with xml
|
271
|
+
# (case independent comparison) and all attribute information items with [prefix] property having
|
272
|
+
# no value and which have [local name] beginning with xml (case independent comparison) are removed.
|
273
|
+
# Note that the [base URI] accessor is computed by XML Base before any xml:base attribute information item
|
274
|
+
# is deleted.
|
275
|
+
attrs = {}
|
276
|
+
id = datatype = parseType = resourceAttr = nodeID = nil
|
277
|
+
|
278
|
+
child.attribute_nodes.each do |attr|
|
279
|
+
if attr.namespace.to_s.empty?
|
280
|
+
# The support for a limited set of non-namespaced names is REQUIRED and intended to allow
|
281
|
+
# RDF/XML documents specified in [RDF-MS] to remain valid;
|
282
|
+
# new documents SHOULD NOT use these unqualified attributes and applications
|
283
|
+
# MAY choose to warn when the unqualified form is seen in a document.
|
284
|
+
add_debug(el, "Unqualified attribute '#{attr}'")
|
285
|
+
#attrs[attr.to_s] = attr.value unless attr.to_s.match?(/^xml/)
|
286
|
+
elsif attr.namespace.href == XML_NS.uri.to_s
|
287
|
+
# No production. Lang and base elements already extracted
|
288
|
+
elsif attr.namespace.href == RDF.uri.to_s
|
289
|
+
case attr.name
|
290
|
+
when "ID" then id = attr.value
|
291
|
+
when "datatype" then datatype = attr.value
|
292
|
+
when "parseType" then parseType = attr.value
|
293
|
+
when "resource" then resourceAttr = attr.value
|
294
|
+
when "nodeID" then nodeID = attr.value
|
295
|
+
else attrs[attr] = attr.value
|
296
|
+
end
|
297
|
+
else
|
298
|
+
attrs[attr] = attr.value
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
if nodeID && resourceAttr
|
303
|
+
add_debug(el, "Cannot have rdf:nodeID and rdf:resource.")
|
304
|
+
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:resource.") if @strict
|
305
|
+
end
|
306
|
+
|
307
|
+
# Apply character transformations
|
308
|
+
id = id_check(el, id.rdf_escape, nil) if id
|
309
|
+
resourceAttr = resourceAttr.rdf_escape if resourceAttr
|
310
|
+
nodeID = nodeID_check(el, nodeID.rdf_escape) if nodeID
|
311
|
+
|
312
|
+
add_debug(child, "attrs: #{attrs.inspect}")
|
313
|
+
add_debug(child, "datatype: #{datatype}") if datatype
|
314
|
+
add_debug(child, "parseType: #{parseType}") if parseType
|
315
|
+
add_debug(child, "resource: #{resourceAttr}") if resourceAttr
|
316
|
+
add_debug(child, "nodeID: #{nodeID}") if nodeID
|
317
|
+
add_debug(child, "id: #{id}") if id
|
318
|
+
|
319
|
+
if attrs.empty? && datatype.nil? && parseType.nil? && element_nodes.length == 1
|
320
|
+
# Production resourcePropertyElt
|
321
|
+
|
322
|
+
new_ec = child_ec.clone(nil)
|
323
|
+
new_node_element = element_nodes.first
|
324
|
+
add_debug(child, "resourcePropertyElt: #{node_path(new_node_element)}")
|
325
|
+
new_subject = nodeElement(new_node_element, new_ec)
|
326
|
+
add_triple(child, subject, predicate, new_subject)
|
327
|
+
elsif attrs.empty? && parseType.nil? && element_nodes.length == 0 && text_nodes.length > 0
|
328
|
+
# Production literalPropertyElt
|
329
|
+
add_debug(child, "literalPropertyElt")
|
330
|
+
|
331
|
+
literal = RDF::Literal.new(child.inner_html, :datatype => datatype, :language => child_ec.language)
|
332
|
+
add_triple(child, subject, predicate, literal)
|
333
|
+
reify(id, child, subject, predicate, literal, ec) if id
|
334
|
+
elsif parseType == "Resource"
|
335
|
+
# Production parseTypeResourcePropertyElt
|
336
|
+
add_debug(child, "parseTypeResourcePropertyElt")
|
337
|
+
|
338
|
+
unless attrs.empty?
|
339
|
+
warn = "Resource Property with extra attributes: '#{attrs.inspect}'"
|
340
|
+
add_debug(child, warn)
|
341
|
+
raise RDF::ReaderError.new(warn) if @strict
|
342
|
+
end
|
343
|
+
|
344
|
+
# For element e with possibly empty element content c.
|
345
|
+
n = BNode.new
|
346
|
+
add_triple(child, subject, predicate, n)
|
347
|
+
|
348
|
+
# Reification
|
349
|
+
reify(id, child, subject, predicate, n, child_ec) if id
|
350
|
+
|
351
|
+
# If the element content c is not empty, then use event n to create a new sequence of events as follows:
|
352
|
+
#
|
353
|
+
# start-element(URI := rdf:Description,
|
354
|
+
# subject := n,
|
355
|
+
# attributes := set())
|
356
|
+
# c
|
357
|
+
# end-element()
|
358
|
+
add_debug(child, "compose new sequence with rdf:Description")
|
359
|
+
node = child.clone
|
360
|
+
pt_attr = node.attribute("parseType")
|
361
|
+
node.namespace = pt_attr.namespace
|
362
|
+
node.attributes.keys.each {|a| node.remove_attribute(a)}
|
363
|
+
node.node_name = "Description"
|
364
|
+
new_ec = child_ec.clone(nil, :subject => n)
|
365
|
+
nodeElement(node, new_ec)
|
366
|
+
elsif parseType == "Collection"
|
367
|
+
# Production parseTypeCollectionPropertyElt
|
368
|
+
add_debug(child, "parseTypeCollectionPropertyElt")
|
369
|
+
|
370
|
+
unless attrs.empty?
|
371
|
+
warn = "Resource Property with extra attributes: '#{attrs.inspect}'"
|
372
|
+
add_debug(child, warn)
|
373
|
+
raise RDF::ReaderError.new(warn) if @strict
|
374
|
+
end
|
375
|
+
|
376
|
+
# For element event e with possibly empty nodeElementList l. Set s:=list().
|
377
|
+
# For each element event f in l, n := bnodeid(identifier := generated-blank-node-id()) and append n to s to give a sequence of events.
|
378
|
+
s = element_nodes.map { RDF::Node.new }
|
379
|
+
n = s.first || RDF["nil"]
|
380
|
+
add_triple(child, subject, predicate, n)
|
381
|
+
reify(id, child, subject, predicate, n, child_ec) if id
|
382
|
+
|
383
|
+
# Add first/rest entries for all list elements
|
384
|
+
s.each_index do |i|
|
385
|
+
n = s[i]
|
386
|
+
o = s[i+1]
|
387
|
+
f = element_nodes[i]
|
388
|
+
|
389
|
+
new_ec = child_ec.clone(nil)
|
390
|
+
object = nodeElement(f, new_ec)
|
391
|
+
add_triple(child, n, RDF.first, object)
|
392
|
+
add_triple(child, n, RDF.rest, o ? o : RDF.nil)
|
393
|
+
end
|
394
|
+
elsif parseType # Literal or Other
|
395
|
+
# Production parseTypeResourcePropertyElt
|
396
|
+
add_debug(child, parseType == "Literal" ? "parseTypeResourcePropertyElt" : "parseTypeOtherPropertyElt (#{parseType})")
|
397
|
+
|
398
|
+
unless attrs.empty?
|
399
|
+
warn = "Resource Property with extra attributes: '#{attrs.inspect}'"
|
400
|
+
add_debug(child, warn)
|
401
|
+
raise RDF::ReaderError.new(warn) if @strict
|
402
|
+
end
|
403
|
+
|
404
|
+
if resourceAttr
|
405
|
+
warn = "illegal rdf:resource"
|
406
|
+
add_debug(child, warn)
|
407
|
+
raise RDF::ReaderError.new(warn) if @strict
|
408
|
+
end
|
409
|
+
|
410
|
+
object = RDF::Literal.new(child.children, :datatype => XML_LITERAL, :namespaces => child_ec.uri_mappings)
|
411
|
+
add_triple(child, subject, predicate, object)
|
412
|
+
elsif text_nodes.length == 0 && element_nodes.length == 0
|
413
|
+
# Production emptyPropertyElt
|
414
|
+
add_debug(child, "emptyPropertyElt")
|
415
|
+
|
416
|
+
if attrs.empty? && resourceAttr.nil? && nodeID.nil?
|
417
|
+
literal = RDF::Literal.new("", :language => ec.language)
|
418
|
+
add_triple(child, subject, predicate, literal)
|
419
|
+
|
420
|
+
# Reification
|
421
|
+
reify(id, child, subject, predicate, literal, child_ec) if id
|
422
|
+
else
|
423
|
+
if resourceAttr
|
424
|
+
resource = ec.base.join(resourceAttr)
|
425
|
+
elsif nodeID
|
426
|
+
resource = RDF::Node.new(nodeID)
|
427
|
+
else
|
428
|
+
resource = RDF::Node.new
|
429
|
+
end
|
430
|
+
|
431
|
+
# produce triples for attributes
|
432
|
+
attrs.each_pair do |attr, val|
|
433
|
+
add_debug(el, "attr: #{attr.name}='#{val}'")
|
434
|
+
|
435
|
+
if attr.uri.to_s == RDF.type
|
436
|
+
add_triple(child, resource, RDF.type, val)
|
437
|
+
else
|
438
|
+
# Check for illegal attributes
|
439
|
+
next unless is_propertyAttr?(attr)
|
440
|
+
|
441
|
+
# Attributes not in RDF.type
|
442
|
+
lit = RDF::Literal.new(val, :language => child_ec.language)
|
443
|
+
add_triple(child, resource, attr.uri.to_s, lit)
|
444
|
+
end
|
445
|
+
end
|
446
|
+
add_triple(child, subject, predicate, resource)
|
447
|
+
|
448
|
+
# Reification
|
449
|
+
reify(id, child, subject, predicate, resource, child_ec) if id
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
# Return subject
|
455
|
+
subject
|
456
|
+
end
|
457
|
+
|
458
|
+
private
|
459
|
+
# Reify subject, predicate, and object given the EvaluationContext (ec) and current XMl element (el)
|
460
|
+
def reify(id, el, subject, predicate, object, ec)
|
461
|
+
add_debug(el, "reify, id: #{id}")
|
462
|
+
rsubject = ec.base.join("#" + id)
|
463
|
+
add_triple(el, rsubject, RDF.subject, subject)
|
464
|
+
add_triple(el, rsubject, RDF.predicate, predicate)
|
465
|
+
add_triple(el, rsubject, RDF.object, object)
|
466
|
+
add_triple(el, rsubject, RDF.type, RDF.Statement)
|
467
|
+
end
|
468
|
+
|
469
|
+
# Figure out the subject from the element.
|
470
|
+
def parse_subject(el, ec)
|
471
|
+
old_property_check(el)
|
472
|
+
|
473
|
+
nodeElementURI_check(el)
|
474
|
+
about = el.attribute("about")
|
475
|
+
id = el.attribute("ID")
|
476
|
+
nodeID = el.attribute("nodeID")
|
477
|
+
|
478
|
+
if nodeID && about
|
479
|
+
add_debug(el, "Cannot have rdf:nodeID and rdf:about.")
|
480
|
+
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:about.") if @strict
|
481
|
+
elsif nodeID && id
|
482
|
+
add_debug(el, "Cannot have rdf:nodeID and rdf:ID.")
|
483
|
+
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:ID.") if @strict
|
484
|
+
end
|
485
|
+
|
486
|
+
case
|
487
|
+
when id
|
488
|
+
add_debug(el, "parse_subject, id: '#{id.value.rdf_escape}'")
|
489
|
+
id_check(el, id.value.rdf_escape, ec.base) # Returns URI
|
490
|
+
when nodeID
|
491
|
+
# The value of rdf:nodeID must match the XML Name production
|
492
|
+
nodeID = nodeID_check(el, nodeID.value.rdf_escape)
|
493
|
+
add_debug(el, "parse_subject, nodeID: '#{nodeID}")
|
494
|
+
RDF::Node.new(nodeID, @named_bnodes)
|
495
|
+
when about
|
496
|
+
about = about.value.rdf_escape
|
497
|
+
add_debug(el, "parse_subject, about: '#{about}'")
|
498
|
+
ec.base.join(about)
|
499
|
+
else
|
500
|
+
add_debug(el, "parse_subject, BNode")
|
501
|
+
RDF::Node.new
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
# ID attribute must be an NCName
|
506
|
+
def id_check(el, id, base)
|
507
|
+
if NC_REGEXP.match(id)
|
508
|
+
# ID may only be specified once for the same URI
|
509
|
+
if base
|
510
|
+
uri = base.join("##{id}", base)
|
511
|
+
if @id_mapping[id] && @id_mapping[id] == uri
|
512
|
+
warn = "ID addtribute '#{id}' may only be defined once for the same URI"
|
513
|
+
add_debug(el, warn)
|
514
|
+
raise RDF::ReaderError.new(warn) if @strict
|
515
|
+
end
|
516
|
+
|
517
|
+
@id_mapping[id] = uri
|
518
|
+
# Returns URI, in this case
|
519
|
+
else
|
520
|
+
id
|
521
|
+
end
|
522
|
+
else
|
523
|
+
warn = "ID addtribute '#{id}' must be a NCName"
|
524
|
+
add_debug(el, "ID addtribute '#{id}' must be a NCName")
|
525
|
+
add_debug(el, warn)
|
526
|
+
raise RDF::ReaderError.new(warn) if @strict
|
527
|
+
nil
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
# nodeID must be an XML Name
|
532
|
+
# nodeID must pass Production rdf-id
|
533
|
+
def nodeID_check(el, nodeID)
|
534
|
+
if NC_REGEXP.match(nodeID)
|
535
|
+
nodeID
|
536
|
+
else
|
537
|
+
add_debug(el, "nodeID addtribute '#{nodeID}' must be an XML Name")
|
538
|
+
raise RDF::ReaderError.new("nodeID addtribute '#{nodeID}' must be a NCName") if @strict
|
539
|
+
nil
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
# Is this attribute a Property Attribute?
|
544
|
+
def is_propertyAttr?(attr)
|
545
|
+
if ([RDF.Description.to_s, RDF.li.to_s] + OLD_TERMS).include?(attr.uri.to_s)
|
546
|
+
warn = "Invalid use of rdf:#{attr.name}"
|
547
|
+
add_debug(attr, warn)
|
548
|
+
raise RDF::ReaderError.new(warn) if @strict
|
549
|
+
return false
|
550
|
+
end
|
551
|
+
!CORE_SYNTAX_TERMS.include?(attr.uri.to_s) && attr.namespace && attr.namespace.href != XML_NS.uri.to_s
|
552
|
+
end
|
553
|
+
|
554
|
+
# Check Node Element name
|
555
|
+
def nodeElementURI_check(el)
|
556
|
+
if (CORE_SYNTAX_TERMS + [RDF.li.to_s] + OLD_TERMS).include?(el.uri.to_s)
|
557
|
+
warn = "Invalid use of rdf:#{el.name}"
|
558
|
+
add_debug(el, warn)
|
559
|
+
raise RDF::ReaderError.new(warn) if @strict
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
# Check Property Element name
|
564
|
+
def propertyElementURI_check(el)
|
565
|
+
if (CORE_SYNTAX_TERMS + [RDF.Description.to_s] + OLD_TERMS).include?(el.uri.to_s)
|
566
|
+
warn = "Invalid use of rdf:#{el.name}"
|
567
|
+
add_debug(el, warn)
|
568
|
+
raise RDF::ReaderError.new(warn) if @strict
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
# Check for the use of an obsolete RDF property
|
573
|
+
def old_property_check(el)
|
574
|
+
el.attribute_nodes.each do |attr|
|
575
|
+
if OLD_TERMS.include?(attr.uri.to_s)
|
576
|
+
add_debug(el, "Obsolete attribute '#{attr.uri}'")
|
577
|
+
raise RDF::ReaderError.new("Obsolete attribute '#{attr.uri}'") if @strict
|
578
|
+
end
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
end
|
583
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RDF::RDFXML::VERSION
|
2
|
+
MAJOR = 0
|
3
|
+
MINOR = 0
|
4
|
+
TINY = 1
|
5
|
+
EXTRA = nil
|
6
|
+
|
7
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
8
|
+
STRING << "-#{EXTRA}" if EXTRA
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [String]
|
12
|
+
def self.to_s() STRING end
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [String]
|
16
|
+
def self.to_str() STRING end
|
17
|
+
|
18
|
+
##
|
19
|
+
# @return [Array(Integer, Integer, Integer)]
|
20
|
+
def self.to_a() [MAJOR, MINOR, TINY] end
|
21
|
+
end
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rdf-rdfxml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
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: 2010-06-03 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rdf
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 1
|
33
|
+
- 6
|
34
|
+
version: 0.1.6
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: nokogiri
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 29
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 3
|
49
|
+
- 3
|
50
|
+
version: 1.3.3
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rspec
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rdf-spec
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: activesupport
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 3
|
90
|
+
segments:
|
91
|
+
- 2
|
92
|
+
- 3
|
93
|
+
- 0
|
94
|
+
version: 2.3.0
|
95
|
+
type: :development
|
96
|
+
version_requirements: *id005
|
97
|
+
description: " RDF::RDFXML is an RDF/XML reader and writer for Ruby using the RDF.rb library suite.\n"
|
98
|
+
email: gregg@kellogg-assoc.com
|
99
|
+
executables: []
|
100
|
+
|
101
|
+
extensions: []
|
102
|
+
|
103
|
+
extra_rdoc_files:
|
104
|
+
- AUTHORS
|
105
|
+
- History.txt
|
106
|
+
- README.rdoc
|
107
|
+
files:
|
108
|
+
- .yardopts
|
109
|
+
- AUTHORS
|
110
|
+
- History.txt
|
111
|
+
- README.rdoc
|
112
|
+
- Rakefile
|
113
|
+
- VERSION
|
114
|
+
- example.rb
|
115
|
+
- lib/rdf/rdfxml.rb
|
116
|
+
- lib/rdf/rdfxml/format.rb
|
117
|
+
- lib/rdf/rdfxml/reader.rb
|
118
|
+
- lib/rdf/rdfxml/version.rb
|
119
|
+
- lib/rdf/rdfxml/writer.rb
|
120
|
+
has_rdoc: true
|
121
|
+
homepage: http://github.com/gkellogg/rdf-rdfxml
|
122
|
+
licenses: []
|
123
|
+
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options:
|
126
|
+
- --charset=UTF-8
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
hash: 3
|
135
|
+
segments:
|
136
|
+
- 0
|
137
|
+
version: "0"
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
hash: 3
|
144
|
+
segments:
|
145
|
+
- 0
|
146
|
+
version: "0"
|
147
|
+
requirements: []
|
148
|
+
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 1.3.7
|
151
|
+
signing_key:
|
152
|
+
specification_version: 3
|
153
|
+
summary: RDF/XML reader/writer for RDF.rb.
|
154
|
+
test_files: []
|
155
|
+
|