rdf-rdfxml 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/.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
|
+
|