rdf_context 0.5.7 → 0.5.8.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/History.rdoc +15 -1
- data/README.rdoc +2 -0
- data/Rakefile +2 -4
- data/VERSION +1 -1
- data/bin/rdf_context +5 -54
- data/lib/rdf_context.rb +5 -0
- data/lib/rdf_context/graph.rb +68 -49
- data/lib/rdf_context/n3parser.rb +2 -2
- data/lib/rdf_context/namespace.rb +1 -1
- data/lib/rdf_context/nokogiri_hacks.rb +7 -0
- data/lib/rdf_context/parser.rb +57 -13
- data/lib/rdf_context/rdfaparser.rb +200 -130
- data/lib/rdf_context/rdfxmlparser.rb +8 -8
- data/lib/rdf_context/serializer/recursive_serializer.rb +1 -1
- data/lib/rdf_context/serializer/turtle_serializer.rb +15 -15
- data/lib/rdf_context/serializer/xml_serializer.rb +8 -8
- data/lib/rdf_context/store/memory_store.rb +14 -14
- data/lib/rdf_context/store/sqlite3_store.rb +4 -4
- data/lib/rdf_context/uriref.rb +11 -4
- data/script/console +1 -3
- data/script/tc +44 -0
- data/spec/.gitignore +1 -0
- data/spec/aggregate_graph_spec.rb +1 -0
- data/spec/bnode_spec.rb +2 -1
- data/spec/conjunctive_graph_spec.rb +1 -0
- data/spec/cwm_spec.rb +1 -0
- data/spec/duration_spec.rb +1 -0
- data/spec/graph_spec.rb +27 -0
- data/spec/list_store_spec.rb +1 -0
- data/spec/literal_spec.rb +1 -0
- data/spec/matchers.rb +1 -1
- data/spec/memory_store_spec.rb +1 -0
- data/spec/n3parser_spec.rb +1 -0
- data/spec/namespaces_spec.rb +1 -0
- data/spec/parser_spec.rb +1 -0
- data/spec/rdf_helper.rb +4 -4
- data/spec/rdfa_helper.rb +24 -0
- data/spec/rdfa_parser_spec.rb +6 -36
- data/spec/rdfcore/.gitignore +1 -0
- data/spec/rdfxml_spec.rb +1 -0
- data/spec/sqlite3_store_spec.rb +1 -0
- data/spec/string_hacks_spec.rb +2 -0
- data/spec/swap_test/.gitignore +1 -0
- data/spec/triple_spec.rb +1 -0
- data/spec/turtle/.gitignore +1 -0
- data/spec/turtle_serializer_spec.rb +3 -2
- data/spec/turtle_spec.rb +1 -0
- data/spec/uriref_spec.rb +13 -12
- data/spec/xml_serializer_spec.rb +7 -6
- metadata +26 -61
- data/spec/html4-manifest.yml +0 -4937
- data/spec/html5-manifest.yml +0 -4937
- data/spec/rdfcore/Manifest.yml +0 -6242
- data/spec/swap_test/n3parser.yml +0 -773
- data/spec/swap_test/regression.yml +0 -902
- data/spec/turtle/manifest-bad.yml +0 -807
- data/spec/turtle/manifest.yml +0 -807
- data/spec/xhtml-manifest.yml +0 -3901
- data/spec/xhtml11-manifest.yml +0 -4405
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'parser')
|
2
|
+
require 'open-uri'
|
2
3
|
|
3
4
|
module RdfContext
|
4
5
|
##
|
@@ -6,11 +7,24 @@ module RdfContext
|
|
6
7
|
#
|
7
8
|
# Based on processing rules described here:
|
8
9
|
# @see http://www.w3.org/TR/rdfa-syntax/#s_model RDFa 1.0
|
9
|
-
# @see http://www.w3.org/2010/02/rdfa/drafts/2010/
|
10
|
+
# @see http://www.w3.org/2010/02/rdfa/drafts/2010/WD-rdfa-core-20100803/ RDFa 1.1
|
10
11
|
#
|
11
12
|
# @author Ben Adida
|
12
13
|
# @author Gregg Kellogg
|
13
14
|
class RdfaParser < Parser
|
15
|
+
SafeCURIEorCURIEorURI = {
|
16
|
+
:rdfa_1_0 => [:term, :safe_curie, :uri, :bnode],
|
17
|
+
:rdfa_1_1 => [:safe_curie, :curie, :term, :uri, :bnode],
|
18
|
+
}
|
19
|
+
TERMorCURIEorAbsURI = {
|
20
|
+
:rdfa_1_0 => [:term, :curie],
|
21
|
+
:rdfa_1_1 => [:term, :curie, :absuri],
|
22
|
+
}
|
23
|
+
TERMorCURIEorAbsURIprop = {
|
24
|
+
:rdfa_1_0 => [:curie],
|
25
|
+
:rdfa_1_1 => [:term, :curie, :absuri],
|
26
|
+
}
|
27
|
+
|
14
28
|
# Host language
|
15
29
|
# @return [:xhtml]
|
16
30
|
attr_reader :host_language
|
@@ -83,7 +97,7 @@ module RdfContext
|
|
83
97
|
# @return [URIRef]
|
84
98
|
attr :default_vocabulary, true
|
85
99
|
|
86
|
-
# @param [
|
100
|
+
# @param [URIRef] base
|
87
101
|
# @param [Hash] host_defaults
|
88
102
|
# @option host_defaults [Hash{String => URIRef}] :term_mappings Hash of NCName => URIRef
|
89
103
|
# @option host_defaults [Hash{String => Namespace}] :vocabulary Hash of prefix => URIRef
|
@@ -92,7 +106,7 @@ module RdfContext
|
|
92
106
|
@base = base
|
93
107
|
@parent_subject = @base
|
94
108
|
@parent_object = nil
|
95
|
-
@uri_mappings = {}
|
109
|
+
@uri_mappings = host_defaults.fetch(:uri_mappings, {})
|
96
110
|
@incomplete_triples = []
|
97
111
|
@language = nil
|
98
112
|
@term_mappings = host_defaults.fetch(:term_mappings, {})
|
@@ -121,6 +135,7 @@ module RdfContext
|
|
121
135
|
# Creates a new parser for RDFa.
|
122
136
|
#
|
123
137
|
# @option options [Graph] :graph (nil) Graph to parse into, otherwise a new RdfContext::Graph instance is created
|
138
|
+
# @option options [Graph] :processor_graph (nil) Graph to record information, warnings and errors.
|
124
139
|
# @option options [Array] :debug (nil) Array to place debug messages
|
125
140
|
# @option options [:rdfxml, :html, :n3] :type (nil)
|
126
141
|
# @option options [Boolean] :strict (false) Raise Error if true, continue with lax parsing, otherwise
|
@@ -140,6 +155,8 @@ module RdfContext
|
|
140
155
|
# @param [Nokogiri::HTML::Document, Nokogiri::XML::Document, #read, #to_s] stream the HTML+RDFa IO stream, string, Nokogiri::HTML::Document or Nokogiri::XML::Document
|
141
156
|
# @param [String] uri (nil) the URI of the document
|
142
157
|
# @option options [Array] :debug (nil) Array to place debug messages
|
158
|
+
# @option options [:rdfa_1_0, :rdfa_1_1] :version (:rdfa_1_1) Parser version information
|
159
|
+
# @option options [:xhtml] :host_language (:xhtml) Host Language
|
143
160
|
# @option options [Boolean] :strict (false) Raise Error if true, continue with lax parsing, otherwise
|
144
161
|
# @return [Graph] Returns the graph containing parsed triples
|
145
162
|
# @yield [triple]
|
@@ -154,22 +171,19 @@ module RdfContext
|
|
154
171
|
else Nokogiri::XML.parse(stream, uri.to_s)
|
155
172
|
end
|
156
173
|
|
157
|
-
|
174
|
+
add_error(nil, "Empty document", RDFA_NS.HostLanguageMarkupError) if @doc.nil?
|
175
|
+
add_warning(nil, "Synax errors:\n#{@doc.errors}", RDFA_NS.HostLanguageMarkupError) unless @doc.errors.empty?
|
176
|
+
|
158
177
|
@callback = block
|
159
178
|
|
160
|
-
|
161
|
-
|
162
|
-
version = @doc.root.attributes["version"].to_s if @doc.root
|
163
|
-
|
164
|
-
@host_language = case version.to_s
|
165
|
-
when /XHTML+RDFa/ then :xhtml
|
166
|
-
end
|
167
|
-
|
168
|
-
# If none found, assume xhtml
|
169
|
-
@host_language ||= :xhtml
|
170
|
-
|
171
|
-
@version = version.to_s.match(/RDFa 1.0/) ? :rdfa_1_0 : :rdfa_1_1
|
179
|
+
@version = options[:version] ? options[:version].to_sym : :rdfa_1_1
|
180
|
+
@host_language = options[:host_language] || :xhtml
|
172
181
|
|
182
|
+
# Section 4.2 RDFa Host Language Conformance
|
183
|
+
#
|
184
|
+
# The Host Language may define a default RDFa Profile. If it does, the RDFa Profile triples that establish term or
|
185
|
+
# URI mappings associated with that profile must not change without changing the profile URI. RDFa Processors may
|
186
|
+
# embed, cache, or retrieve the RDFa Profile triples associated with that profile.
|
173
187
|
@host_defaults = case @host_language
|
174
188
|
when :xhtml
|
175
189
|
@graph.bind(XHV_NS)
|
@@ -188,7 +202,7 @@ module RdfContext
|
|
188
202
|
|
189
203
|
@host_defaults.delete(:vocabulary) if @version == :rdfa_1_0
|
190
204
|
|
191
|
-
add_debug(@doc, "version = #{@version}, host_language = #{@host_language}")
|
205
|
+
add_debug(@doc.root, "version = #{@version.inspect}, host_language = #{@host_language}")
|
192
206
|
# parse
|
193
207
|
parse_whole_document(@doc, @uri)
|
194
208
|
|
@@ -206,51 +220,45 @@ module RdfContext
|
|
206
220
|
base = base_el.attributes['href']
|
207
221
|
# Strip any fragment from base
|
208
222
|
base = base.to_s.split("#").first
|
209
|
-
@uri = URIRef.
|
223
|
+
@uri = URIRef.intern(base, :normalize => false, :normalize => false)
|
210
224
|
add_debug(base_el, "parse_whole_doc: base='#{base}'")
|
211
225
|
end
|
212
226
|
|
213
227
|
# initialize the evaluation context with the appropriate base
|
214
|
-
evaluation_context = EvaluationContext.new(
|
228
|
+
evaluation_context = EvaluationContext.new(@uri, @host_defaults)
|
215
229
|
|
216
230
|
traverse(doc.root, evaluation_context)
|
217
231
|
end
|
218
232
|
|
219
|
-
#
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
# If @profile is present, its value is processed as defined in RDFa Profiles.
|
225
|
-
element.attributes['profile'].to_s.split(/\s/).each do |profile|
|
233
|
+
# Parse and process URI mappings, Term mappings and a default vocabulary from @profile
|
234
|
+
#
|
235
|
+
# Yields each mapping
|
236
|
+
def process_profile(element)
|
237
|
+
element.attributes['profile'].to_s.split(/\s/).reverse.each do |profile|
|
226
238
|
# Don't try to open ourselves!
|
227
239
|
if @uri == profile
|
228
|
-
add_debug(element, "
|
229
|
-
@@vocabulary_cache[profile]
|
240
|
+
add_debug(element, "process_profile: skip recursive profile <#{profile}>")
|
230
241
|
elsif @@vocabulary_cache.has_key?(profile)
|
231
|
-
add_debug(element, "
|
242
|
+
add_debug(element, "process_profile: skip previously parsed profile <#{profile}>")
|
232
243
|
else
|
233
244
|
begin
|
234
|
-
add_debug(element, "extract_mappings: parse profile <#{profile}>")
|
235
245
|
@@vocabulary_cache[profile] = {
|
236
246
|
:uri_mappings => {},
|
237
|
-
:term_mappings => {}
|
247
|
+
:term_mappings => {},
|
248
|
+
:default_vocabulary => nil
|
238
249
|
}
|
239
250
|
um = @@vocabulary_cache[profile][:uri_mappings]
|
240
251
|
tm = @@vocabulary_cache[profile][:term_mappings]
|
241
|
-
add_debug(element, "
|
242
|
-
|
243
|
-
|
244
|
-
sess.timeout = 10
|
245
|
-
resp = sess.get(profile)
|
246
|
-
raise RuntimeError, "HTTP returned status #{resp.status} when reading #{profile}" if resp.status >= 400
|
252
|
+
add_debug(element, "process_profile: parse profile <#{profile}>")
|
253
|
+
prof_body = OpenURI.open_uri(profile)
|
254
|
+
raise ParserException, "Empty profile #{profile}" if prof_body.to_s.empty?
|
247
255
|
|
248
256
|
# Parse profile, and extract mappings from graph
|
249
|
-
old_debug, old_verbose, =
|
250
|
-
|
251
|
-
p_graph = Parser.parse(
|
252
|
-
ttl = p_graph.serialize(:format => :ttl) if @debug ||
|
253
|
-
|
257
|
+
old_debug, old_verbose, = ::RdfContext::debug?, $verbose
|
258
|
+
::RdfContext::debug, $verbose = false, false
|
259
|
+
p_graph = Parser.parse(prof_body, profile)
|
260
|
+
ttl = p_graph.serialize(:format => :ttl) if @debug || ::RdfContext::debug?
|
261
|
+
::RdfContext::debug, $verbose = old_debug, old_verbose
|
254
262
|
add_debug(element, ttl) if ttl
|
255
263
|
p_graph.subjects.each do |subject|
|
256
264
|
props = p_graph.properties(subject)
|
@@ -261,19 +269,24 @@ module RdfContext
|
|
261
269
|
uri = props[RDFA_NS.uri_.to_s]
|
262
270
|
term = props[RDFA_NS.term_.to_s]
|
263
271
|
prefix = props[RDFA_NS.prefix_.to_s]
|
264
|
-
|
272
|
+
vocab = props[RDFA_NS.vocabulary.to_s]
|
273
|
+
add_debug(element, "process_profile: uri=#{uri.inspect}, term=#{term.inspect}, prefix=#{prefix.inspect}, vocabulary=#{vocab.inspect}")
|
265
274
|
|
266
|
-
|
267
|
-
raise ParserException, "multi-valued rdf:uri" if uri.length != 1
|
275
|
+
raise ParserException, "multi-valued rdf:uri" if uri && uri.length != 1
|
268
276
|
raise ParserException, "multi-valued rdf:term." if term && term.length != 1
|
269
277
|
raise ParserException, "multi-valued rdf:prefix" if prefix && prefix.length != 1
|
278
|
+
raise ParserException, "multi-valued rdf:vocabulary" if vocab && vocab.length != 1
|
270
279
|
|
271
|
-
uri = uri.first
|
280
|
+
uri = uri.first if uri
|
272
281
|
term = term.first if term
|
273
282
|
prefix = prefix.first if prefix
|
274
|
-
|
275
|
-
raise ParserException, "rdf:
|
276
|
-
raise ParserException, "rdf:
|
283
|
+
vocab = vocab.first if vocab
|
284
|
+
raise ParserException, "rdf:uri #{uri.inspect} must be a Literal" unless uri.nil? || uri.is_a?(Literal)
|
285
|
+
raise ParserException, "rdf:term #{term.inspect} must be a Literal" unless term.nil? || term.is_a?(Literal)
|
286
|
+
raise ParserException, "rdf:prefix #{prefix.inspect} must be a Literal" unless prefix.nil? || prefix.is_a?(Literal)
|
287
|
+
raise ParserException, "rdf:vocabulary #{vocab.inspect} must be a Literal" unless vocab.nil? || vocab.is_a?(Literal)
|
288
|
+
|
289
|
+
@@vocabulary_cache[profile][:default_vocabulary] = vocab if vocab
|
277
290
|
|
278
291
|
# For every extracted triple that is the common subject of an rdfa:prefix and an rdfa:uri
|
279
292
|
# predicate, create a mapping from the object literal of the rdfa:prefix predicate to the
|
@@ -285,38 +298,42 @@ module RdfContext
|
|
285
298
|
# triple that is the common subject of an rdfa:term and an rdfa:uri predicate, create a
|
286
299
|
# mapping from the object literal of the rdfa:term predicate to the object literal of the
|
287
300
|
# rdfa:uri predicate. Add or update this mapping in the local term mappings.
|
288
|
-
tm[term.to_s] = URIRef.
|
301
|
+
tm[term.to_s.downcase] = URIRef.intern(uri.to_s, :normalize => false) if term
|
289
302
|
end
|
290
|
-
rescue
|
291
|
-
|
292
|
-
raise
|
293
|
-
rescue RuntimeError => e
|
294
|
-
add_debug(element, "extract_mappings: profile: #{e.message}")
|
295
|
-
raise if @strict
|
303
|
+
rescue Exception => e
|
304
|
+
add_error(element, e.message, RDFA_NS.ProfileReferenceError)
|
305
|
+
raise # We need to be sure processing stops
|
296
306
|
end
|
297
307
|
end
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
end
|
303
|
-
|
308
|
+
profile_mappings = @@vocabulary_cache[profile]
|
309
|
+
yield :uri_mappings, profile_mappings[:uri_mappings] unless profile_mappings[:uri_mappings].empty?
|
310
|
+
yield :term_mappings, profile_mappings[:term_mappings] unless profile_mappings[:term_mappings].empty?
|
311
|
+
yield :default_vocabulary, profile_mappings[:default_vocabulary] if profile_mappings[:default_vocabulary]
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
# Extract the XMLNS mappings from an element
|
316
|
+
def extract_mappings(element, uri_mappings)
|
304
317
|
# look for xmlns
|
305
318
|
# (note, this may be dependent on @host_language)
|
306
319
|
# Regardless of how the mapping is declared, the value to be mapped must be converted to lower case,
|
307
320
|
# and the URI is not processed in any way; in particular if it is a relative path it is
|
308
321
|
# not resolved against the current base.
|
309
|
-
element.
|
322
|
+
element.namespace_definitions.each do |ns|
|
323
|
+
add_debug(element, "extract_mappings: namespace #{ns.prefix} => <#{ns.href}>")
|
310
324
|
begin
|
311
|
-
abbr, prefix = attr_name.split(":")
|
312
325
|
# A Conforming RDFa Processor must ignore any definition of a mapping for the '_' prefix.
|
313
|
-
next if prefix == "_"
|
326
|
+
next if ns.prefix == "_"
|
314
327
|
|
315
|
-
|
316
|
-
|
328
|
+
# Downcase prefix for RDFa 1.1
|
329
|
+
pfx_lc = (@version == :rdfa_1_0 || ns.prefix.nil?) ? ns.prefix : ns.prefix.to_s.downcase
|
330
|
+
if ns.prefix
|
331
|
+
uri_mappings[pfx_lc] = @graph.bind(Namespace.new(ns.href, ns.prefix.to_s))
|
332
|
+
add_debug(element, "extract_mappings: xmlns:#{ns.prefix} => <#{ns.href}>")
|
333
|
+
end
|
334
|
+
|
317
335
|
rescue RdfException => e
|
318
|
-
|
319
|
-
raise if @strict
|
336
|
+
add_error(element, "extract_mappings raised #{e.class}: #{e.message}")
|
320
337
|
end
|
321
338
|
end
|
322
339
|
|
@@ -335,10 +352,8 @@ module RdfContext
|
|
335
352
|
next if prefix == "_"
|
336
353
|
|
337
354
|
uri_mappings[prefix] = @graph.bind(Namespace.new(uri, prefix))
|
355
|
+
add_debug(element, "extract_mappings: prefix #{prefix} => <#{uri}>")
|
338
356
|
end unless @version == :rdfa_1_0
|
339
|
-
|
340
|
-
add_debug(element, "uri_mappings: #{uri_mappings.values.map{|ns|ns.to_s}.join(", ")}")
|
341
|
-
add_debug(element, "term_mappings: #{term_mappings.keys.join(", ")}")
|
342
357
|
end
|
343
358
|
|
344
359
|
# The recursive helper function
|
@@ -351,7 +366,7 @@ module RdfContext
|
|
351
366
|
|
352
367
|
add_debug(element, "traverse, ec: #{evaluation_context.inspect}")
|
353
368
|
|
354
|
-
# local variables [
|
369
|
+
# local variables [7.5 Step 1]
|
355
370
|
recurse = true
|
356
371
|
skip = false
|
357
372
|
new_subject = nil
|
@@ -374,31 +389,54 @@ module RdfContext
|
|
374
389
|
vocab = attrs['vocab']
|
375
390
|
|
376
391
|
# Pull out the attributes needed for the skip test.
|
377
|
-
property = attrs['property'].to_s if attrs['property']
|
378
|
-
typeof = attrs['typeof'].to_s if attrs['typeof']
|
392
|
+
property = attrs['property'].to_s.strip if attrs['property']
|
393
|
+
typeof = attrs['typeof'].to_s.strip if attrs['typeof']
|
379
394
|
datatype = attrs['datatype'].to_s if attrs['datatype']
|
380
395
|
content = attrs['content'].to_s if attrs['content']
|
381
|
-
rel = attrs['rel'].to_s if attrs['rel']
|
382
|
-
rev = attrs['rev'].to_s if attrs['rev']
|
396
|
+
rel = attrs['rel'].to_s.strip if attrs['rel']
|
397
|
+
rev = attrs['rev'].to_s.strip if attrs['rev']
|
383
398
|
|
384
|
-
#
|
385
|
-
#
|
399
|
+
# Local term mappings [7.5 Steps 2]
|
400
|
+
# Next the current element is parsed for any updates to the local term mappings and local list of URI mappings via @profile.
|
401
|
+
# If @profile is present, its value is processed as defined in RDFa Profiles.
|
402
|
+
unless @version == :rdfa_1_0
|
403
|
+
begin
|
404
|
+
process_profile(element) do |which, value|
|
405
|
+
add_debug(element, "[Step 2] traverse, #{which}: #{value.inspect}")
|
406
|
+
case which
|
407
|
+
when :uri_mappings then uri_mappings.merge!(value)
|
408
|
+
when :term_mappings then term_mappings.merge!(value)
|
409
|
+
when :default_vocabulary then default_vocabulary = value
|
410
|
+
end
|
411
|
+
end
|
412
|
+
rescue
|
413
|
+
# Skip this element and all sub-elements
|
414
|
+
# If any referenced RDFa Profile is not available, then the current element and its children must not place any
|
415
|
+
# triples in the default graph .
|
416
|
+
raise if @strict
|
417
|
+
return
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# Default vocabulary [7.5 Step 3]
|
422
|
+
# Next the current element is examined for any change to the default vocabulary via @vocab.
|
386
423
|
# If @vocab is present and contains a value, its value updates the local default vocabulary.
|
387
424
|
# If the value is empty, then the local default vocabulary must be reset to the Host Language defined default.
|
388
425
|
unless vocab.nil?
|
389
426
|
default_vocabulary = if vocab.to_s.empty?
|
427
|
+
add_debug(element, "[Step 2] traverse, reset default_vocaulary to #{@host_defaults.fetch(:vocabulary, nil).inspect}")
|
390
428
|
# Set default_vocabulary to host language default
|
391
429
|
@host_defaults.fetch(:vocabulary, nil)
|
392
430
|
else
|
393
|
-
URIRef.
|
431
|
+
URIRef.intern(vocab)
|
394
432
|
end
|
395
433
|
add_debug(element, "[Step 2] traverse, default_vocaulary: #{default_vocabulary.inspect}")
|
396
434
|
end
|
397
435
|
|
398
|
-
# Local term mappings [7.5 Steps
|
399
|
-
# Next the current element is
|
400
|
-
#
|
401
|
-
extract_mappings(element, uri_mappings
|
436
|
+
# Local term mappings [7.5 Steps 4]
|
437
|
+
# Next, the current element is then examined for URI mapping s and these are added to the local list of URI mappings.
|
438
|
+
# Note that a URI mapping will simply overwrite any current mapping in the list that has the same name
|
439
|
+
extract_mappings(element, uri_mappings)
|
402
440
|
|
403
441
|
# Language information [7.5 Step 5]
|
404
442
|
# From HTML5 [3.2.3.3]
|
@@ -421,12 +459,12 @@ module RdfContext
|
|
421
459
|
:uri_mappings => uri_mappings,
|
422
460
|
:term_mappings => term_mappings,
|
423
461
|
:vocab => default_vocabulary,
|
424
|
-
:
|
462
|
+
:restrictions => TERMorCURIEorAbsURI[@version])
|
425
463
|
revs = process_uris(element, rev, evaluation_context,
|
426
464
|
:uri_mappings => uri_mappings,
|
427
465
|
:term_mappings => term_mappings,
|
428
466
|
:vocab => default_vocabulary,
|
429
|
-
:
|
467
|
+
:restrictions => TERMorCURIEorAbsURI[@version])
|
430
468
|
|
431
469
|
add_debug(element, "traverse, about: #{about.nil? ? 'nil' : about}, src: #{src.nil? ? 'nil' : src}, resource: #{resource.nil? ? 'nil' : resource}, href: #{href.nil? ? 'nil' : href}")
|
432
470
|
add_debug(element, "traverse, property: #{property.nil? ? 'nil' : property}, typeof: #{typeof.nil? ? 'nil' : typeof}, datatype: #{datatype.nil? ? 'nil' : datatype}, content: #{content.nil? ? 'nil' : content}")
|
@@ -438,15 +476,15 @@ module RdfContext
|
|
438
476
|
new_subject = if about
|
439
477
|
process_uri(element, about, evaluation_context,
|
440
478
|
:uri_mappings => uri_mappings,
|
441
|
-
:
|
479
|
+
:restrictions => SafeCURIEorCURIEorURI[@version])
|
442
480
|
elsif src
|
443
|
-
process_uri(element, src, evaluation_context, :
|
481
|
+
process_uri(element, src, evaluation_context, :restrictions => [:uri])
|
444
482
|
elsif resource
|
445
483
|
process_uri(element, resource, evaluation_context,
|
446
484
|
:uri_mappings => uri_mappings,
|
447
|
-
:
|
485
|
+
:restrictions => SafeCURIEorCURIEorURI[@version])
|
448
486
|
elsif href
|
449
|
-
process_uri(element, href, evaluation_context, :
|
487
|
+
process_uri(element, href, evaluation_context, :restrictions => [:uri])
|
450
488
|
end
|
451
489
|
|
452
490
|
# If no URI is provided by a resource attribute, then the first match from the following rules
|
@@ -459,7 +497,7 @@ module RdfContext
|
|
459
497
|
# From XHTML+RDFa 1.1:
|
460
498
|
# if no URI is provided, then first check to see if the element is the head or body element.
|
461
499
|
# If it is, then act as if there is an empty @about present, and process it according to the rule for @about.
|
462
|
-
|
500
|
+
evaluation_context.base
|
463
501
|
elsif element.attributes['typeof']
|
464
502
|
BNode.new
|
465
503
|
else
|
@@ -472,16 +510,19 @@ module RdfContext
|
|
472
510
|
# [7.5 Step 7]
|
473
511
|
# If the current element does contain a @rel or @rev attribute, then the next step is to
|
474
512
|
# establish both a value for new subject and a value for current object resource:
|
475
|
-
new_subject = process_uri(element, about
|
513
|
+
new_subject = process_uri(element, about, evaluation_context,
|
476
514
|
:uri_mappings => uri_mappings,
|
477
|
-
:
|
478
|
-
|
515
|
+
:restrictions => SafeCURIEorCURIEorURI[@version]) ||
|
516
|
+
process_uri(element, src, evaluation_context,
|
517
|
+
:uri_mappings => uri_mappings,
|
518
|
+
:restrictions => [:uri])
|
519
|
+
|
479
520
|
# If no URI is provided then the first match from the following rules will apply
|
480
521
|
new_subject ||= if @host_language == :xhtml && element.name =~ /^(head|body)$/
|
481
522
|
# From XHTML+RDFa 1.1:
|
482
523
|
# if no URI is provided, then first check to see if the element is the head or body element.
|
483
524
|
# If it is, then act as if there is an empty @about present, and process it according to the rule for @about.
|
484
|
-
|
525
|
+
evaluation_context.base
|
485
526
|
elsif element.attributes['typeof']
|
486
527
|
BNode.new
|
487
528
|
else
|
@@ -494,10 +535,10 @@ module RdfContext
|
|
494
535
|
current_object_resource = if resource
|
495
536
|
process_uri(element, resource, evaluation_context,
|
496
537
|
:uri_mappings => uri_mappings,
|
497
|
-
:
|
538
|
+
:restrictions => SafeCURIEorCURIEorURI[@version])
|
498
539
|
elsif href
|
499
540
|
process_uri(element, href, evaluation_context,
|
500
|
-
:
|
541
|
+
:restrictions => [:uri])
|
501
542
|
end
|
502
543
|
|
503
544
|
add_debug(element, "[Step 7] new_subject: #{new_subject}, current_object_resource = #{current_object_resource.nil? ? 'nil' : current_object_resource}")
|
@@ -505,12 +546,12 @@ module RdfContext
|
|
505
546
|
|
506
547
|
# Process @typeof if there is a subject [Step 8]
|
507
548
|
if new_subject and typeof
|
508
|
-
# Typeof is
|
549
|
+
# Typeof is TERMorCURIEorAbsURIs
|
509
550
|
types = process_uris(element, typeof, evaluation_context,
|
510
551
|
:uri_mappings => uri_mappings,
|
511
552
|
:term_mappings => term_mappings,
|
512
553
|
:vocab => default_vocabulary,
|
513
|
-
:
|
554
|
+
:restrictions => TERMorCURIEorAbsURI[@version])
|
514
555
|
add_debug(element, "typeof: #{typeof}")
|
515
556
|
types.each do |one_type|
|
516
557
|
add_triple(element, new_subject, RDF_TYPE, one_type)
|
@@ -546,7 +587,7 @@ module RdfContext
|
|
546
587
|
:uri_mappings => uri_mappings,
|
547
588
|
:term_mappings => term_mappings,
|
548
589
|
:vocab => default_vocabulary,
|
549
|
-
:
|
590
|
+
:restrictions => TERMorCURIEorAbsURIprop[@version])
|
550
591
|
|
551
592
|
properties.reject! do |p|
|
552
593
|
if p.is_a?(URIRef)
|
@@ -559,28 +600,40 @@ module RdfContext
|
|
559
600
|
end
|
560
601
|
|
561
602
|
# get the literal datatype
|
562
|
-
type = datatype
|
563
603
|
children_node_types = element.children.collect{|c| c.class}.uniq
|
564
604
|
|
565
605
|
# the following 3 IF clauses should be mutually exclusive. Written as is to prevent extensive indentation.
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
current_object_literal = if
|
606
|
+
datatype = process_uri(element, datatype, evaluation_context,
|
607
|
+
:uri_mappings => uri_mappings,
|
608
|
+
:term_mappings => term_mappings,
|
609
|
+
:vocab => default_vocabulary,
|
610
|
+
:restrictions => TERMorCURIEorAbsURI[@version]) unless datatype.to_s.empty?
|
611
|
+
current_object_literal = if !datatype.to_s.empty? && datatype.to_s != XML_LITERAL.to_s
|
572
612
|
# typed literal
|
573
613
|
add_debug(element, "[Step 11] typed literal")
|
574
|
-
Literal.typed(content || element.inner_text,
|
575
|
-
elsif
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
614
|
+
Literal.typed(content || element.inner_text, datatype, :language => language)
|
615
|
+
elsif @version == :rdfa_1_1
|
616
|
+
if datatype.to_s == XML_LITERAL.to_s
|
617
|
+
# XML Literal
|
618
|
+
add_debug(element, "[Step 11(1.1)] XML Literal: #{element.inner_html}")
|
619
|
+
recurse = false
|
620
|
+
Literal.typed(element.children, XML_LITERAL, :language => language, :namespaces => uri_mappings)
|
621
|
+
else
|
622
|
+
# plain literal
|
623
|
+
add_debug(element, "[Step 11(1.1)] plain literal")
|
624
|
+
Literal.untyped(content || element.inner_text, language)
|
625
|
+
end
|
626
|
+
else
|
627
|
+
if content || (children_node_types == [Nokogiri::XML::Text]) || (element.children.length == 0) || datatype == ""
|
628
|
+
# plain literal
|
629
|
+
add_debug(element, "[Step 11 (1.0)] plain literal")
|
630
|
+
Literal.untyped(content || element.inner_text, language)
|
631
|
+
elsif children_node_types != [Nokogiri::XML::Text] and (datatype == nil or datatype.to_s == XML_LITERAL.to_s)
|
632
|
+
# XML Literal
|
633
|
+
add_debug(element, "[Step 11 (1.0)] XML Literal: #{element.inner_html}")
|
634
|
+
recurse = false
|
635
|
+
Literal.typed(element.children, XML_LITERAL, :language => language, :namespaces => uri_mappings)
|
636
|
+
end
|
584
637
|
end
|
585
638
|
|
586
639
|
# add each property
|
@@ -640,7 +693,7 @@ module RdfContext
|
|
640
693
|
end
|
641
694
|
end
|
642
695
|
|
643
|
-
# space-separated
|
696
|
+
# space-separated TERMorCURIEorAbsURI or SafeCURIEorCURIEorURI
|
644
697
|
def process_uris(element, value, evaluation_context, options)
|
645
698
|
return [] if value.to_s.empty?
|
646
699
|
add_debug(element, "process_uris: #{value}")
|
@@ -649,8 +702,8 @@ module RdfContext
|
|
649
702
|
|
650
703
|
def process_uri(element, value, evaluation_context, options = {})
|
651
704
|
return if value.nil?
|
652
|
-
restrictions =
|
653
|
-
add_debug(element, "process_uri: restrictions = #{restrictions.inspect}")
|
705
|
+
restrictions = options[:restrictions]
|
706
|
+
add_debug(element, "process_uri: #{value}, restrictions = #{restrictions.inspect}")
|
654
707
|
options = {:uri_mappings => {}}.merge(options)
|
655
708
|
if !options[:term_mappings] && options[:uri_mappings] && value.to_s.match(/^\[(.*)\]$/) && restrictions.include?(:safe_curie)
|
656
709
|
# SafeCURIEorCURIEorURI
|
@@ -659,25 +712,38 @@ module RdfContext
|
|
659
712
|
# value must be ignored.
|
660
713
|
uri = curie_to_resource_or_bnode(element, $1, options[:uri_mappings], evaluation_context.parent_subject, restrictions)
|
661
714
|
add_debug(element, "process_uri: #{value} => safeCURIE => <#{uri}>")
|
715
|
+
|
662
716
|
uri
|
663
717
|
elsif options[:term_mappings] && NC_REGEXP.match(value.to_s) && restrictions.include?(:term)
|
664
|
-
#
|
718
|
+
# TERMorCURIEorAbsURI
|
665
719
|
# If the value is an NCName, then it is evaluated as a term according to General Use of Terms in
|
666
720
|
# Attributes. Note that this step may mean that the value is to be ignored.
|
667
|
-
uri = process_term(value.to_s, options)
|
721
|
+
uri = process_term(element, value.to_s, options)
|
668
722
|
add_debug(element, "process_uri: #{value} => term => <#{uri}>")
|
669
723
|
uri
|
670
724
|
else
|
671
|
-
# SafeCURIEorCURIEorURI or
|
725
|
+
# SafeCURIEorCURIEorURI or TERMorCURIEorAbsURI
|
672
726
|
# Otherwise, the value is evaluated as a CURIE.
|
673
727
|
# If it is a valid CURIE, the resulting URI is used; otherwise, the value will be processed as a URI.
|
674
728
|
uri = curie_to_resource_or_bnode(element, value, options[:uri_mappings], evaluation_context.parent_subject, restrictions)
|
675
729
|
if uri
|
676
730
|
add_debug(element, "process_uri: #{value} => CURIE => <#{uri}>")
|
677
|
-
elsif @version == :rdfa_1_0 && value.to_s.match(/^xml/)
|
731
|
+
elsif @version == :rdfa_1_0 && value.to_s.match(/^xml/i)
|
678
732
|
# Special case to not allow anything starting with XML to be treated as a URI
|
679
|
-
|
680
|
-
|
733
|
+
elsif restrictions.include?(:absuri) || restrictions.include?(:uri)
|
734
|
+
begin
|
735
|
+
# AbsURI does not use xml:base
|
736
|
+
uri = URIRef.intern(value, restrictions.include?(:absuri) ? nil : evaluation_context.base, :normalize => false)
|
737
|
+
rescue Addressable::URI::InvalidURIError => e
|
738
|
+
add_warning(element, "Malformed prefix #{value}", RDFA_NS.UndefinedPrefixError)
|
739
|
+
rescue ParserException => e
|
740
|
+
add_debug(element, e.message)
|
741
|
+
if value.to_s =~ /^\(^\w\):/
|
742
|
+
add_warning(element, "Undefined prefix #{$1}", RDFA_NS.UndefinedPrefixError)
|
743
|
+
else
|
744
|
+
add_warning(element, "Relative URI #{value}")
|
745
|
+
end
|
746
|
+
end
|
681
747
|
add_debug(element, "process_uri: #{value} => URI => <#{uri}>")
|
682
748
|
end
|
683
749
|
uri
|
@@ -690,17 +756,17 @@ module RdfContext
|
|
690
756
|
# @param [Hash] options:: Parser options, one of
|
691
757
|
# <em>options[:term_mappings]</em>:: Term mappings
|
692
758
|
# <em>options[:vocab]</em>:: Default vocabulary
|
693
|
-
def process_term(value, options)
|
759
|
+
def process_term(element, value, options)
|
694
760
|
case
|
695
761
|
when options[:term_mappings].is_a?(Hash) && options[:term_mappings].has_key?(value.to_s.downcase)
|
696
762
|
# If the term is in the local term mappings, use the associated URI.
|
697
|
-
# XXX Spec Confusion: are terms always downcased? Or only for XHTML Vocab?
|
698
763
|
options[:term_mappings][value.to_s.downcase]
|
699
764
|
when options[:vocab]
|
700
765
|
# Otherwise, if there is a local default vocabulary the URI is obtained by concatenating that value and the term.
|
701
|
-
URIRef.
|
766
|
+
URIRef.intern(options[:vocab].to_s + value)
|
702
767
|
else
|
703
768
|
# Finally, if there is no local default vocabulary, the term has no associated URI and must be ignored.
|
769
|
+
add_warning(element, "Term #{value} is not defined", RDFA_NS.UndefinedTermError)
|
704
770
|
nil
|
705
771
|
end
|
706
772
|
end
|
@@ -713,6 +779,7 @@ module RdfContext
|
|
713
779
|
# consider the bnode situation
|
714
780
|
if prefix == "_" && restrictions.include?(:bnode)
|
715
781
|
# we force a non-nil name, otherwise it generates a new name
|
782
|
+
# As a special case, _: is also a valid reference for one specific bnode.
|
716
783
|
BNode.new(reference || "", @named_bnodes)
|
717
784
|
elsif curie.to_s.match(/^:/)
|
718
785
|
add_debug(element, "curie_to_resource_or_bnode: default prefix: defined? #{!!uri_mappings[""]}, defaults: #{@host_defaults[:prefix]}")
|
@@ -721,6 +788,9 @@ module RdfContext
|
|
721
788
|
uri_mappings[""].send("#{reference}_")
|
722
789
|
elsif @host_defaults[:prefix]
|
723
790
|
@host_defaults[:prefix].send("#{reference}_")
|
791
|
+
else
|
792
|
+
#add_warning(element, "Default namespace prefix is not defined", RDFA_NS.UndefinedPrefixError)
|
793
|
+
nil
|
724
794
|
end
|
725
795
|
elsif !curie.to_s.match(/:/)
|
726
796
|
# No prefix, undefined (in this context, it is evaluated as a term elsewhere)
|
@@ -732,7 +802,7 @@ module RdfContext
|
|
732
802
|
if ns
|
733
803
|
ns + reference
|
734
804
|
else
|
735
|
-
add_debug(element, "curie_to_resource_or_bnode No namespace mapping for #{prefix}")
|
805
|
+
#add_debug(element, "curie_to_resource_or_bnode No namespace mapping for #{prefix}")
|
736
806
|
nil
|
737
807
|
end
|
738
808
|
end
|