rdf-rdfxml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ --title "RDF::RDFa - RDFa Support for RDF.rb"
2
+ --output-dir doc/yard
3
+ --protected
4
+ --no-private
5
+ --hide-void-return
6
+ --markup rdoc
7
+ --readme README.rdoc
8
+ -
9
+ AUTHORS
10
+ VERSION
data/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ * Gregg Kellogg <gregg@kellogg-assoc.com>
@@ -0,0 +1,2 @@
1
+ === 0.0.1
2
+ * First port from RdfContext version 0.5.4
@@ -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
@@ -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
@@ -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
@@ -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) # &#x301; 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
+