rdf-rdfa 0.3.1.2 → 0.3.3
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 +2 -1
- data/Gemfile +18 -0
- data/History.md +14 -1
- data/README +291 -0
- data/README.md +236 -36
- data/Rakefile +7 -27
- data/UNLICENSE +24 -0
- data/VERSION +1 -1
- data/etc/basic.html +1 -1
- data/etc/profile.html +40 -0
- data/example-files/payswarm.html +449 -0
- data/example-files/payswarm.n3 +86 -0
- data/lib/rdf/rdfa.rb +5 -0
- data/lib/rdf/rdfa/format.rb +8 -4
- data/lib/rdf/rdfa/patches/graph_properties.rb +34 -0
- data/lib/rdf/rdfa/patches/nokogiri_hacks.rb +6 -0
- data/lib/rdf/rdfa/patches/string_hacks.rb +9 -0
- data/lib/rdf/rdfa/profile.rb +65 -41
- data/lib/rdf/rdfa/profile/xhtml.rb +36 -0
- data/lib/rdf/rdfa/profile/xml.rb +45 -0
- data/lib/rdf/rdfa/reader.rb +168 -92
- data/lib/rdf/rdfa/writer.rb +822 -0
- data/lib/rdf/rdfa/writer/haml_templates.rb +306 -0
- data/rdf-rdfa.gemspec +77 -23
- data/script/intern_vocabulary +83 -0
- data/script/parse +62 -27
- data/script/tc +87 -37
- data/spec/.gitignore +1 -0
- data/spec/matchers.rb +89 -154
- data/spec/profile_spec.rb +36 -21
- data/spec/{rdfa_reader_spec.rb → reader_spec.rb} +86 -159
- data/spec/spec_helper.rb +6 -29
- data/spec/test_helper.rb +97 -0
- data/spec/writer_spec.rb +385 -0
- metadata +203 -37
- data/spec/html4-manifest.yml +0 -1749
- data/spec/html5-manifest.yml +0 -1749
- data/spec/rdfa_helper.rb +0 -257
- data/spec/svgtiny-manifest.yml +0 -37
- data/spec/xhtml-manifest.yml +0 -1749
@@ -0,0 +1,86 @@
|
|
1
|
+
@base <http://recipes.payswarm.com/?p=10185> .
|
2
|
+
@prefix bibo: <http://purl.org/ontology/bibo/> .
|
3
|
+
@prefix cal: <http://www.w3.org/2002/12/cal/ical#> .
|
4
|
+
@prefix cc: <http://creativecommons.org/ns#> .
|
5
|
+
@prefix com: <http://purl.org/commerce#> .
|
6
|
+
@prefix dbp: <http://dbpedia.org/property/> .
|
7
|
+
@prefix dbp-owl: <http://dbpedia.org/ontology/> .
|
8
|
+
@prefix dbr: <http://dbpedia.org/resource/> .
|
9
|
+
@prefix dc: <http://purl.org/dc/terms/> .
|
10
|
+
@prefix dcterms: <http://purl.org/dc/terms/> .
|
11
|
+
@prefix doap: <http://usefulinc.com/ns/doap#> .
|
12
|
+
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
13
|
+
@prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
|
14
|
+
@prefix gr: <http://purl.org/goodrelations/v1#> .
|
15
|
+
@prefix grddl: <http://www.w3.org/2003/g/data-view#> .
|
16
|
+
@prefix og: <http://ogp.me/ns#> .
|
17
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
18
|
+
@prefix ps: <http://purl.org/payswarm#> .
|
19
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
20
|
+
@prefix rdfa: <http://www.w3.org/ns/rdfa#> .
|
21
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
22
|
+
@prefix rif: <http://www.w3.org/2007/rif#> .
|
23
|
+
@prefix rss: <http://purl.org/rss/1.0/> .
|
24
|
+
@prefix sd: <http://www.w3.org/ns/sparql-service-description#> .
|
25
|
+
@prefix sig: <http://purl.org/signature#> .
|
26
|
+
@prefix sioc: <http://rdfs.org/sioc/ns#> .
|
27
|
+
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
|
28
|
+
@prefix skosxl: <http://www.w3.org/2008/05/skos-xl#> .
|
29
|
+
@prefix v: <http://rdf.data-vocabulary.org/#> .
|
30
|
+
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .
|
31
|
+
@prefix void: <http://rdfs.org/ns/void#> .
|
32
|
+
@prefix wdr: <http://www.w3.org/2007/05/powder#> .
|
33
|
+
@prefix wdrs: <http://www.w3.org/2007/05/powder-s#> .
|
34
|
+
@prefix xhv: <http://www.w3.org/1999/xhtml/vocab#> .
|
35
|
+
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
|
36
|
+
@prefix xmlns: <http://www.w3.org/2000/xmlns/> .
|
37
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
38
|
+
|
39
|
+
<#listing> com:payee <#listing-payee>;
|
40
|
+
com:payeeRule [ com:destinationOwnerType ps:Authority;
|
41
|
+
com:maximumRate "11.45"@en-US;
|
42
|
+
com:rateContext com:Inclusive,
|
43
|
+
com:Tax,
|
44
|
+
com:TaxExempt;
|
45
|
+
com:rateType com:Percentage;
|
46
|
+
a com:PayeeRule];
|
47
|
+
ps:asset <#asset>;
|
48
|
+
ps:assetHash "025b9b9f1eea31a9431f0c181a22df8a8257fc49"@en-US;
|
49
|
+
ps:license <http://purl.org/payswarm/licenses/blogging>;
|
50
|
+
ps:licenseHash "b94ba441c42432e82b6e3a076f4c614f83cac6ef"@en-US;
|
51
|
+
ps:validFrom "2011-04-18T00:00:00+0000"^^xsd:dateTime;
|
52
|
+
ps:validUntil "2011-04-19T00:00:00+0000"^^xsd:dateTime;
|
53
|
+
sig:signature [ dc:created "2011-04-18T00:00:00Z"^^xsd:dateTime;
|
54
|
+
dc:creator <https://payswarm.com/i/devuser/keys/4>;
|
55
|
+
sig:signatureValue "MqF1r37JSev+2uUKdr1ZOWVfNbTx8YdBZUMW4hlgeQyIiYxfbHF+eYhU+NLFrclTjj3i7qnwREIIBP0O0BFk72JIBl3JcCDKpfbA7pqiFuaGvxr9+Ba7o0pYojo0A6Mc/+0UD5rjdJc+qAH9hnMOzKpjyeMxUcR1Z6w0XXKXc8A="@en-US;
|
56
|
+
a sig:JsonldSignature];
|
57
|
+
a gr:Offering,
|
58
|
+
ps:Listing .
|
59
|
+
<> xhv:alternate <https://recipes.payswarm.com/?feed=comments-rss2>,
|
60
|
+
<https://recipes.payswarm.com/?feed=rss2>,
|
61
|
+
<https://recipes.payswarm.com/?feed=rss2&p=10185>;
|
62
|
+
xhv:bookmark <https://recipes.payswarm.com/?p=10185>;
|
63
|
+
xhv:index <https://recipes.payswarm.com>;
|
64
|
+
xhv:next <https://recipes.payswarm.com/?p=10186>;
|
65
|
+
xhv:prev <https://recipes.payswarm.com/?p=10184>;
|
66
|
+
xhv:start <https://recipes.payswarm.com/?p=1>;
|
67
|
+
xhv:stylesheet <https://recipes.payswarm.com/wp-content/plugins/payswarm/payswarm.css?ver=3.1>,
|
68
|
+
<https://recipes.payswarm.com/wp-content/themes/twentyten/style.css> .
|
69
|
+
<#asset> dc:creator [ foaf:name "chef"@en-US];
|
70
|
+
dc:title "Soft Breadsticks"@en-US;
|
71
|
+
ps:assetProvider <https://dev.payswarm.com:19100/i/devuser>;
|
72
|
+
ps:authority <https://payswarm.dev:19100/client-config>;
|
73
|
+
ps:contentUrl <>;
|
74
|
+
sig:signature [ dc:created "2011-04-18T00:00:00Z"^^xsd:dateTime;
|
75
|
+
dc:creator <https://payswarm.com/i/devuser/keys/4>;
|
76
|
+
sig:signatureValue "GYQHOxTJeyfky4NkxTm/IEcVGKYq7omDXPwdX+CYlJD9ur6RX35jM/RS3SeB7teGlJs1KtAx+l4ZUsAZa4sINYkr9fKh0k0K7TCbXp2X5sJ4ZCE3AvxZfc4IQEMuiiq+C8LHJv6g6tVmdl25UIbfroEBd/Hv+ID995VgapsSmQo="@en-US;
|
77
|
+
a sig:JsonldSignature];
|
78
|
+
a ps:Asset,
|
79
|
+
ps:WebPage .
|
80
|
+
<#listing-payee> com:currency "USD"@en-US;
|
81
|
+
com:destination <https://dev.payswarm.com:19100/i/devuser/accounts/primary>;
|
82
|
+
com:payeePosition "0"^^xsd:integer;
|
83
|
+
com:rate "0.04597"@en-US;
|
84
|
+
com:rateType com:FlatAmount;
|
85
|
+
a com:Payee;
|
86
|
+
rdfs:comment "Payment for Soft Breadsticks by chef."@en-US .
|
data/lib/rdf/rdfa.rb
CHANGED
@@ -27,10 +27,15 @@ module RDF
|
|
27
27
|
require 'rdf/rdfa/vocab'
|
28
28
|
require 'rdf/rdfa/patches/literal_hacks'
|
29
29
|
require 'rdf/rdfa/patches/nokogiri_hacks'
|
30
|
+
require 'rdf/rdfa/patches/string_hacks'
|
30
31
|
autoload :Profile, 'rdf/rdfa/profile'
|
31
32
|
autoload :Reader, 'rdf/rdfa/reader'
|
33
|
+
autoload :Writer, 'rdf/rdfa/writer'
|
32
34
|
autoload :VERSION, 'rdf/rdfa/version'
|
33
35
|
|
36
|
+
XML_RDFA_PROFILE = "http://www.w3.org/profile/rdfa-1.1"
|
37
|
+
XHTML_RDFA_PROFILE = "http://www.w3.org/profile/html-rdfa-1.1"
|
38
|
+
|
34
39
|
def self.debug?; @debug; end
|
35
40
|
def self.debug=(value); @debug = value; end
|
36
41
|
end
|
data/lib/rdf/rdfa/format.rb
CHANGED
@@ -18,12 +18,10 @@ module RDF::RDFa
|
|
18
18
|
#
|
19
19
|
# @see http://www.w3.org/TR/rdf-testcases/#ntriples
|
20
20
|
class Format < RDF::Format
|
21
|
-
content_type 'text/html', :extension => :html
|
22
|
-
content_type 'application/xhtml+xml', :extension => :xhtml
|
23
|
-
content_type 'image/svg+xml', :extension => :svg
|
24
21
|
content_encoding 'utf-8'
|
25
|
-
|
22
|
+
content_type 'text/html', :extension => :html
|
26
23
|
reader { RDF::RDFa::Reader }
|
24
|
+
writer { RDF::RDFa::Writer }
|
27
25
|
XMLNS = 'http://www.w3.org/1999/xhtml' # FIXME: This or XHV or none at all?
|
28
26
|
end
|
29
27
|
|
@@ -36,6 +34,8 @@ module RDF::RDFa
|
|
36
34
|
# RDF::Format.for(:html).reader # RDF::RDFa::Reader
|
37
35
|
# RDF::Format.for(:html).writer # RDF::RDFa::Writer
|
38
36
|
class HTML < RDF::Format
|
37
|
+
content_encoding 'utf-8'
|
38
|
+
content_type 'text/html', :extension => :html
|
39
39
|
reader { RDF::RDFa::Reader }
|
40
40
|
writer { RDF::RDFa::Writer }
|
41
41
|
end
|
@@ -49,6 +49,8 @@ module RDF::RDFa
|
|
49
49
|
# RDF::Format.for(:xhtml).reader # RDF::RDFa::Reader
|
50
50
|
# RDF::Format.for(:xhtml).writer # RDF::RDFa::Writer
|
51
51
|
class XHTML < RDF::Format
|
52
|
+
content_encoding 'utf-8'
|
53
|
+
content_type 'application/xhtml+xml', :extension => :xhtml
|
52
54
|
reader { RDF::RDFa::Reader }
|
53
55
|
writer { RDF::RDFa::Writer }
|
54
56
|
end
|
@@ -62,6 +64,8 @@ module RDF::RDFa
|
|
62
64
|
# RDF::Format.for(:svg).reader # RDF::RDFa::Reader
|
63
65
|
# RDF::Format.for(:svg).writer # RDF::RDFa::Writer
|
64
66
|
class SVG < RDF::Format
|
67
|
+
content_encoding 'utf-8'
|
68
|
+
content_type 'image/svg+xml', :extension => :svg
|
65
69
|
reader { RDF::RDFa::Reader }
|
66
70
|
writer { RDF::RDFa::Writer }
|
67
71
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module RDF
|
2
|
+
class Graph
|
3
|
+
# Resource properties
|
4
|
+
#
|
5
|
+
# Properties arranged as a hash with the predicate Term as index to an array of resources or literals
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# graph.load(':foo a :bar; rdfs:label "An example" .', "http://example.com/")
|
9
|
+
# graph.resources(URI.new("http://example.com/subject")) =>
|
10
|
+
# {
|
11
|
+
# "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" => [<http://example.com/#bar>],
|
12
|
+
# "http://example.com/#label" => ["An example"]
|
13
|
+
# }
|
14
|
+
def properties(subject, recalc = false)
|
15
|
+
@properties ||= {}
|
16
|
+
@properties.delete(subject.to_s) if recalc
|
17
|
+
@properties[subject.to_s] ||= begin
|
18
|
+
hash = Hash.new
|
19
|
+
self.query(:subject => subject) do |statement|
|
20
|
+
pred = statement.predicate.to_s
|
21
|
+
|
22
|
+
hash[pred] ||= []
|
23
|
+
hash[pred] << statement.object
|
24
|
+
end
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get type(s) of subject, returns a list of symbols
|
30
|
+
def type_of(subject)
|
31
|
+
query(:subject => subject, :predicate => RDF.type).map {|st| st.object}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class ::String
|
2
|
+
# Trim beginning of each line by the amount of indentation in the first line
|
3
|
+
def align_left
|
4
|
+
str = self.sub(/^\s*$/, '') # Remove leading newline
|
5
|
+
str = str[1..-1] if str[0,1] == "\n"
|
6
|
+
ws = str.match(/^(\s*)\S/m) ? $1 : ''
|
7
|
+
str.gsub(/^#{ws}/m, '')
|
8
|
+
end
|
9
|
+
end
|
data/lib/rdf/rdfa/profile.rb
CHANGED
@@ -30,45 +30,18 @@ module RDF::RDFa
|
|
30
30
|
# Parses the profile and places it in the repository and cache
|
31
31
|
#
|
32
32
|
# @param [RDF::URI, #to_s] uri URI of profile to be represented
|
33
|
-
|
33
|
+
# @yield [profile]
|
34
|
+
# @yieldparam [RDF::RDFa::Profile] profile
|
35
|
+
# @yieldreturn [void] ignored
|
36
|
+
# @return [RDF::RDFa::Profile]
|
37
|
+
def initialize(uri, options = {}, &block)
|
34
38
|
@uri = RDF::URI.intern(uri)
|
35
|
-
@prefixes = {}
|
36
|
-
@terms = {}
|
37
|
-
@vocabulary =
|
39
|
+
@prefixes = options.fetch(:prefixes, {})
|
40
|
+
@terms = options.fetch(:terms, {})
|
41
|
+
@vocabulary = options[:vocabulary]
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
resource_info = {}
|
42
|
-
repository.query(:context => uri).each do |statement|
|
43
|
-
res = resource_info[statement.subject] ||= {}
|
44
|
-
next unless statement.object.is_a?(RDF::Literal)
|
45
|
-
%w(uri term prefix vocabulary).each do |term|
|
46
|
-
res[term] ||= statement.object.value if statement.predicate == RDF::RDFA[term]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
resource_info.values.each do |res|
|
51
|
-
# If one of the objects is not a Literal or if there are additional rdfa:uri or rdfa:term
|
52
|
-
# predicates sharing the same subject, no mapping is created.
|
53
|
-
uri = res["uri"]
|
54
|
-
term = res["term"]
|
55
|
-
prefix = res["prefix"]
|
56
|
-
vocab = res["vocabulary"]
|
57
|
-
|
58
|
-
@vocabulary = vocab if vocab
|
59
|
-
|
60
|
-
# For every extracted triple that is the common subject of an rdfa:prefix and an rdfa:uri
|
61
|
-
# predicate, create a mapping from the object literal of the rdfa:prefix predicate to the
|
62
|
-
# object literal of the rdfa:uri predicate. Add or update this mapping in the local list of
|
63
|
-
# URI mappings after transforming the 'prefix' component to lower-case.
|
64
|
-
# For every extracted
|
65
|
-
prefix(prefix.downcase, uri) if uri && prefix && prefix != "_"
|
66
|
-
|
67
|
-
# triple that is the common subject of an rdfa:term and an rdfa:uri predicate, create a
|
68
|
-
# mapping from the object literal of the rdfa:term predicate to the object literal of the
|
69
|
-
# rdfa:uri predicate. Add or update this mapping in the local term mappings.
|
70
|
-
term(term, uri) if term && uri
|
71
|
-
end
|
43
|
+
yield(self) if block_given?
|
44
|
+
self
|
72
45
|
end
|
73
46
|
|
74
47
|
##
|
@@ -76,7 +49,9 @@ module RDF::RDFa
|
|
76
49
|
# @private
|
77
50
|
def self.cache
|
78
51
|
require 'rdf/util/cache' unless defined?(::RDF::Util::Cache)
|
79
|
-
@cache ||=
|
52
|
+
@cache ||= begin
|
53
|
+
RDF::Util::Cache.new(-1)
|
54
|
+
end
|
80
55
|
end
|
81
56
|
|
82
57
|
##
|
@@ -107,9 +82,13 @@ module RDF::RDFa
|
|
107
82
|
# Return something to make the caller happy if we're re-entered
|
108
83
|
cache[uri] = Struct.new(:prefixes, :terms, :vocabulary).new({}, {}, nil)
|
109
84
|
# Now do the actual load
|
110
|
-
cache[uri] = new(uri)
|
85
|
+
cache[uri] = new(uri) do |profile|
|
86
|
+
STDERR.puts("process_profile: retrieve profile <#{uri}>") if RDF::RDFa.debug?
|
87
|
+
Profile.load(uri)
|
88
|
+
profile.parse(repository.query(:context => uri))
|
89
|
+
end
|
111
90
|
rescue Exception => e
|
112
|
-
raise ProfileError, "
|
91
|
+
raise ProfileError, "Profile #{uri}: #{e.message}"
|
113
92
|
end
|
114
93
|
|
115
94
|
# Load profile into repository
|
@@ -166,10 +145,55 @@ module RDF::RDFa
|
|
166
145
|
name = name.to_s.empty? ? nil : (name.respond_to?(:to_sym) ? name.to_sym : name.to_s.to_sym)
|
167
146
|
uri.nil? ? terms[name] : terms[name] = uri
|
168
147
|
end
|
148
|
+
|
149
|
+
##
|
150
|
+
# Extract vocabulary, prefix mappings and terms from a enumerable object into an instance
|
151
|
+
#
|
152
|
+
# @param [RDF::Enumerable, Enumerator] queryable
|
153
|
+
# @return [void] ignored
|
154
|
+
def parse(enumerable)
|
155
|
+
STDERR.puts("process_profile: parse profile <#{uri}>") if RDF::RDFa.debug?
|
156
|
+
resource_info = {}
|
157
|
+
enumerable.each do |statement|
|
158
|
+
res = resource_info[statement.subject] ||= {}
|
159
|
+
next unless statement.object.is_a?(RDF::Literal)
|
160
|
+
STDERR.puts("process_profile: statement=#{statement.inspect}") if RDF::RDFa.debug?
|
161
|
+
%w(uri term prefix vocabulary).each do |term|
|
162
|
+
res[term] ||= statement.object.value if statement.predicate == RDF::RDFA[term]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
resource_info.values.each do |res|
|
167
|
+
# If one of the objects is not a Literal or if there are additional rdfa:uri or rdfa:term
|
168
|
+
# predicates sharing the same subject, no mapping is created.
|
169
|
+
uri = res["uri"]
|
170
|
+
term = res["term"]
|
171
|
+
prefix = res["prefix"]
|
172
|
+
vocab = res["vocabulary"]
|
173
|
+
STDERR.puts("process_profile: uri=#{uri.inspect}, term=#{term.inspect}, prefix=#{prefix.inspect}, vocabulary=#{vocab.inspect}") if RDF::RDFa.debug?
|
174
|
+
|
175
|
+
@vocabulary = vocab if vocab
|
176
|
+
|
177
|
+
# For every extracted triple that is the common subject of an rdfa:prefix and an rdfa:uri
|
178
|
+
# predicate, create a mapping from the object literal of the rdfa:prefix predicate to the
|
179
|
+
# object literal of the rdfa:uri predicate. Add or update this mapping in the local list of
|
180
|
+
# URI mappings after transforming the 'prefix' component to lower-case.
|
181
|
+
# For every extracted
|
182
|
+
prefix(prefix.downcase, uri) if uri && prefix && prefix != "_"
|
183
|
+
|
184
|
+
# triple that is the common subject of an rdfa:term and an rdfa:uri predicate, create a
|
185
|
+
# mapping from the object literal of the rdfa:term predicate to the object literal of the
|
186
|
+
# rdfa:uri predicate. Add or update this mapping in the local term mappings.
|
187
|
+
term(term, uri) if term && uri
|
188
|
+
end
|
189
|
+
end
|
169
190
|
end
|
170
191
|
|
171
192
|
##
|
172
193
|
# The base class for RDF profile errors.
|
173
194
|
class ProfileError < IOError
|
174
195
|
end # ProfileError
|
175
|
-
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Load cooked profiles
|
199
|
+
Dir.glob(File.join(File.expand_path(File.dirname(__FILE__)), 'profile', '*')).each {|f| load f}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# This file is automatically generated by script/intern_vocabulary
|
2
|
+
# RDFa vocabulary for http://www.w3.org/profile/html-rdfa-1.1
|
3
|
+
|
4
|
+
profile = RDF::RDFa::Profile.new(RDF::URI("http://www.w3.org/profile/html-rdfa-1.1"), {
|
5
|
+
:terms => {
|
6
|
+
:alternate => "http://www.w3.org/1999/xhtml/vocab#alternate",
|
7
|
+
:appendix => "http://www.w3.org/1999/xhtml/vocab#appendix",
|
8
|
+
:bookmark => "http://www.w3.org/1999/xhtml/vocab#bookmark",
|
9
|
+
:chapter => "http://www.w3.org/1999/xhtml/vocab#chapter",
|
10
|
+
:cite => "http://www.w3.org/1999/xhtml/vocab#cite",
|
11
|
+
:contents => "http://www.w3.org/1999/xhtml/vocab#contents",
|
12
|
+
:copyright => "http://www.w3.org/1999/xhtml/vocab#copyright",
|
13
|
+
:first => "http://www.w3.org/1999/xhtml/vocab#first",
|
14
|
+
:glossary => "http://www.w3.org/1999/xhtml/vocab#glossary",
|
15
|
+
:help => "http://www.w3.org/1999/xhtml/vocab#help",
|
16
|
+
:icon => "http://www.w3.org/1999/xhtml/vocab#icon",
|
17
|
+
:index => "http://www.w3.org/1999/xhtml/vocab#index",
|
18
|
+
:itsRules => "http://www.w3.org/1999/xhtml/vocab#itsRules",
|
19
|
+
:last => "http://www.w3.org/1999/xhtml/vocab#last",
|
20
|
+
:license => "http://www.w3.org/1999/xhtml/vocab#license",
|
21
|
+
:meta => "http://www.w3.org/1999/xhtml/vocab#meta",
|
22
|
+
:next => "http://www.w3.org/1999/xhtml/vocab#next",
|
23
|
+
:p3pv1 => "http://www.w3.org/1999/xhtml/vocab#p3pv1",
|
24
|
+
:prev => "http://www.w3.org/1999/xhtml/vocab#prev",
|
25
|
+
:role => "http://www.w3.org/1999/xhtml/vocab#role",
|
26
|
+
:section => "http://www.w3.org/1999/xhtml/vocab#section",
|
27
|
+
:start => "http://www.w3.org/1999/xhtml/vocab#start",
|
28
|
+
:stylesheet => "http://www.w3.org/1999/xhtml/vocab#stylesheet",
|
29
|
+
:subsection => "http://www.w3.org/1999/xhtml/vocab#subsection",
|
30
|
+
:top => "http://www.w3.org/1999/xhtml/vocab#top",
|
31
|
+
:transformation => "http://www.w3.org/2003/g/data-view#transformation",
|
32
|
+
:up => "http://www.w3.org/1999/xhtml/vocab#up",
|
33
|
+
},
|
34
|
+
})
|
35
|
+
|
36
|
+
RDF::RDFa::Profile.cache[RDF::URI("http://www.w3.org/profile/html-rdfa-1.1")] = profile
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# This file is automatically generated by script/intern_vocabulary
|
2
|
+
# RDFa vocabulary for http://www.w3.org/profile/rdfa-1.1
|
3
|
+
|
4
|
+
profile = RDF::RDFa::Profile.new(RDF::URI("http://www.w3.org/profile/rdfa-1.1"), {
|
5
|
+
:prefixes => {
|
6
|
+
:bibo => "http://purl.org/ontology/bibo/",
|
7
|
+
:cal => "http://www.w3.org/2002/12/cal/ical#",
|
8
|
+
:cc => "http://creativecommons.org/ns#",
|
9
|
+
:dbp => "http://dbpedia.org/property/",
|
10
|
+
:"dbp-owl" => "http://dbpedia.org/ontology/",
|
11
|
+
:dbr => "http://dbpedia.org/resource/",
|
12
|
+
:dc => "http://purl.org/dc/elements/1.1/",
|
13
|
+
:dcterms => "http://purl.org/dc/terms/",
|
14
|
+
:doap => "http://usefulinc.com/ns/doap#",
|
15
|
+
:foaf => "http://xmlns.com/foaf/0.1/",
|
16
|
+
:geo => "http://www.w3.org/2003/01/geo/wgs84_pos#",
|
17
|
+
:gr => "http://purl.org/goodrelations/v1#",
|
18
|
+
:grddl => "http://www.w3.org/2003/g/data-view#",
|
19
|
+
:og => "http://ogp.me/ns#",
|
20
|
+
:owl => "http://www.w3.org/2002/07/owl#",
|
21
|
+
:rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
22
|
+
:rdfa => "http://www.w3.org/ns/rdfa#",
|
23
|
+
:rdfs => "http://www.w3.org/2000/01/rdf-schema#",
|
24
|
+
:rif => "http://www.w3.org/2007/rif#",
|
25
|
+
:rss => "http://purl.org/rss/1.0/",
|
26
|
+
:sd => "http://www.w3.org/ns/sparql-service-description#",
|
27
|
+
:sioc => "http://rdfs.org/sioc/ns#",
|
28
|
+
:skos => "http://www.w3.org/2004/02/skos/core#",
|
29
|
+
:skosxl => "http://www.w3.org/2008/05/skos-xl#",
|
30
|
+
:v => "http://rdf.data-vocabulary.org/#",
|
31
|
+
:vcard => "http://www.w3.org/2006/vcard/ns#",
|
32
|
+
:void => "http://rdfs.org/ns/void#",
|
33
|
+
:wdr => "http://www.w3.org/2007/05/powder#",
|
34
|
+
:wdrs => "http://www.w3.org/2007/05/powder-s#",
|
35
|
+
:xhv => "http://www.w3.org/1999/xhtml/vocab#",
|
36
|
+
:xml => "http://www.w3.org/XML/1998/namespace",
|
37
|
+
:xmlns => "http://www.w3.org/2000/xmlns/",
|
38
|
+
:xsd => "http://www.w3.org/2001/XMLSchema#",
|
39
|
+
},
|
40
|
+
:terms => {
|
41
|
+
:describedby => "http://www.w3.org/2007/05/powder-s#describedby",
|
42
|
+
},
|
43
|
+
})
|
44
|
+
|
45
|
+
RDF::RDFa::Profile.cache[RDF::URI("http://www.w3.org/profile/rdfa-1.1")] = profile
|
data/lib/rdf/rdfa/reader.rb
CHANGED
@@ -6,23 +6,24 @@ module RDF::RDFa
|
|
6
6
|
#
|
7
7
|
# Based on processing rules described here:
|
8
8
|
# @see http://www.w3.org/TR/rdfa-syntax/#s_model RDFa 1.0
|
9
|
-
# @see http://www.w3.org/
|
9
|
+
# @see http://www.w3.org/TR/2010/WD-rdfa-core-20100422/ RDFa Core 1.1
|
10
|
+
# @see http://www.w3.org/TR/2010/WD-xhtml-rdfa-20100422/ XHTML+RDFa 1.1
|
10
11
|
#
|
11
12
|
# @author [Gregg Kellogg](http://kellogg-assoc.com/)
|
12
13
|
class Reader < RDF::Reader
|
13
14
|
format Format
|
14
15
|
|
15
16
|
SafeCURIEorCURIEorURI = {
|
16
|
-
:
|
17
|
-
:
|
17
|
+
:"rdfa1.0" => [:term, :safe_curie, :uri, :bnode],
|
18
|
+
:"rdfa1.1" => [:safe_curie, :curie, :term, :uri, :bnode],
|
18
19
|
}
|
19
20
|
TERMorCURIEorAbsURI = {
|
20
|
-
:
|
21
|
-
:
|
21
|
+
:"rdfa1.0" => [:term, :curie],
|
22
|
+
:"rdfa1.1" => [:term, :curie, :absuri],
|
22
23
|
}
|
23
24
|
TERMorCURIEorAbsURIprop = {
|
24
|
-
:
|
25
|
-
:
|
25
|
+
:"rdfa1.0" => [:curie],
|
26
|
+
:"rdfa1.1" => [:term, :curie, :absuri],
|
26
27
|
}
|
27
28
|
|
28
29
|
NC_REGEXP = Regexp.new(
|
@@ -39,11 +40,11 @@ module RDF::RDFa
|
|
39
40
|
Regexp::EXTENDED)
|
40
41
|
|
41
42
|
# Host language
|
42
|
-
# @return [:
|
43
|
+
# @return [:xml1, :xhtml1, :xhtml5, :html4, :html5, :svg]
|
43
44
|
attr_reader :host_language
|
44
45
|
|
45
46
|
# Version
|
46
|
-
# @return [:
|
47
|
+
# @return [:"rdfa1.0", :"rdfa1.1"]
|
47
48
|
attr_reader :version
|
48
49
|
|
49
50
|
# The Recursive Baggage
|
@@ -147,7 +148,7 @@ module RDF::RDFa
|
|
147
148
|
v << "uri_mappings[#{uri_mappings.keys.length}]"
|
148
149
|
v << "incomplete_triples[#{incomplete_triples.length}]"
|
149
150
|
v << "term_mappings[#{term_mappings.keys.length}]"
|
150
|
-
v.join(",")
|
151
|
+
v.join(", ")
|
151
152
|
end
|
152
153
|
end
|
153
154
|
|
@@ -170,9 +171,9 @@ module RDF::RDFa
|
|
170
171
|
# the prefix mappings to use (not supported by all readers)
|
171
172
|
# @option options [#to_s] :base_uri (nil)
|
172
173
|
# the base URI to use when resolving relative URIs
|
173
|
-
# @option options [:
|
174
|
+
# @option options [:xml1, :xhtml1, :xhtml5, :html4, :html5, :svg] :host_language (:xhtml1)
|
174
175
|
# Host Language
|
175
|
-
# @option options [:
|
176
|
+
# @option options [:"rdfa1.0", :"rdfa1.1"] :version (:"rdfa1.1")
|
176
177
|
# Parser version information
|
177
178
|
# @option options [Graph] :processor_graph (nil)
|
178
179
|
# Graph to record information, warnings and errors.
|
@@ -190,24 +191,93 @@ module RDF::RDFa
|
|
190
191
|
@debug = options[:debug]
|
191
192
|
@base_uri = uri(options[:base_uri])
|
192
193
|
|
193
|
-
@
|
194
|
+
@host_language = options[:host_language]
|
194
195
|
@processor_graph = options[:processor_graph]
|
195
196
|
|
196
197
|
@doc = case input
|
197
|
-
when Nokogiri::HTML::Document
|
198
|
-
|
199
|
-
|
198
|
+
when Nokogiri::HTML::Document
|
199
|
+
@host_language ||= :xhtml1
|
200
|
+
when Nokogiri::XML::Document
|
201
|
+
input
|
202
|
+
else
|
203
|
+
# Intuit from content type
|
204
|
+
@host_language ||= case input.respond_to?(:content_type) && input.content_type
|
205
|
+
when "text/xml", "application/xml"
|
206
|
+
:xml1
|
207
|
+
when "text/html", "application/xhtml+xml"
|
208
|
+
:xhtml1
|
209
|
+
when "image/svg+xml"
|
210
|
+
:svg
|
211
|
+
end
|
212
|
+
|
213
|
+
# Intuit from file extension
|
214
|
+
@host_language ||= case input.respond_to?(:path) && File.extname(input.path.to_s)
|
215
|
+
when ".html" then :html5
|
216
|
+
when ".xhtml" then :xhtml1
|
217
|
+
when ".svg" then :svg
|
218
|
+
end
|
219
|
+
|
220
|
+
Nokogiri::XML.parse(input, @base_uri.to_s)
|
200
221
|
end
|
201
222
|
|
202
|
-
@
|
203
|
-
|
223
|
+
if (@doc.nil? || @doc.root.nil?)
|
224
|
+
add_error(nil, "Empty document", RDF::RDFA.DocumentError)
|
225
|
+
raise RDF::ReaderError, "Empty Document"
|
226
|
+
end
|
227
|
+
add_warning(nil, "Synax errors:\n#{@doc.errors}", RDF::RDFA.DocumentError) if !@doc.errors.empty? && validate?
|
228
|
+
|
229
|
+
@version = options[:version] ? options[:version].to_sym : nil
|
230
|
+
|
231
|
+
# Check for version of the processor to use:
|
232
|
+
# * Check document type for "XHTML+RDFa 1.0"
|
233
|
+
# * Check @version attribute on the html element for the value "XHTML+RDFa 1.0"
|
234
|
+
@version ||= :"rdfa1.0" if @doc.doctype.to_s =~ /RDFa 1\.0/
|
235
|
+
@version ||= :"rdfa1.0" if @doc.root && @doc.root.attribute("version").to_s =~ /RDFa 1\.0/
|
236
|
+
@version ||= :"rdfa1.1" if @doc.root && @doc.root.attribute("version").to_s =~ /RDFa 1\.1/
|
237
|
+
@version ||= :"rdfa1.1"
|
238
|
+
|
239
|
+
# Intuit host_language from doctype
|
240
|
+
@host_language ||= case @doc.doctype.to_s
|
241
|
+
when /html 4/i then :html4
|
242
|
+
when /xhtml\+rdfa/i then :xhtml1
|
243
|
+
when /html/ then :html5
|
244
|
+
end
|
245
|
+
|
246
|
+
# Determine host language from element name
|
247
|
+
@host_language ||= case @doc.root.name.downcase.to_sym
|
248
|
+
when :html then :xhtml1
|
204
249
|
when :svg then :svg
|
205
|
-
else :
|
250
|
+
else :xml
|
206
251
|
end
|
207
252
|
|
208
|
-
|
209
|
-
|
210
|
-
|
253
|
+
# Otherwise, treat it as XML
|
254
|
+
@host_language ||= :xml1
|
255
|
+
|
256
|
+
# Section 4.2 RDFa Host Language Conformance
|
257
|
+
#
|
258
|
+
# The Host Language may require the automatic inclusion of one or more default RDFa Profiles.
|
259
|
+
@host_defaults = {
|
260
|
+
:vocabulary => nil,
|
261
|
+
:uri_mappings => {},
|
262
|
+
:profiles => [],
|
263
|
+
}
|
264
|
+
|
265
|
+
if @version == :"rdfa1.0"
|
266
|
+
# Add default term mappings
|
267
|
+
@host_defaults[:term_mappings] = %w(
|
268
|
+
alternate appendix bookmark cite chapter contents copyright first glossary help icon index
|
269
|
+
last license meta next p3pv1 prev role section stylesheet subsection start top up
|
270
|
+
).inject({}) { |hash, term| hash[term] = RDF::XHV[term]; hash }
|
271
|
+
end
|
272
|
+
|
273
|
+
case @host_language
|
274
|
+
when :xml1, :svg
|
275
|
+
@host_defaults[:profiles] = [XML_RDFA_PROFILE]
|
276
|
+
when :xhtml1, :xhtml5, :html4, :html5
|
277
|
+
@host_defaults[:profiles] = [XML_RDFA_PROFILE, XHTML_RDFA_PROFILE]
|
278
|
+
end
|
279
|
+
|
280
|
+
add_info(@doc, "version = #{@version}, host_language = #{@host_language}")
|
211
281
|
|
212
282
|
block.call(self) if block_given?
|
213
283
|
end
|
@@ -234,35 +304,11 @@ module RDF::RDFa
|
|
234
304
|
def each_statement(&block)
|
235
305
|
@callback = block
|
236
306
|
|
237
|
-
# Section 4.2 RDFa Host Language Conformance
|
238
|
-
#
|
239
|
-
# The Host Language may define a default RDFa Profile. If it does, the RDFa Profile triples that establish term or
|
240
|
-
# URI mappings associated with that profile must not change without changing the profile URI. RDFa Processors may
|
241
|
-
# embed, cache, or retrieve the RDFa Profile triples associated with that profile.
|
242
|
-
@host_defaults = case @host_language
|
243
|
-
when :xhtml
|
244
|
-
{
|
245
|
-
:vocabulary => nil,
|
246
|
-
:prefix => "xhv",
|
247
|
-
:uri_mappings => {"xhv" => RDF::XHV.to_s}, # RDF::XHTML is wrong
|
248
|
-
:term_mappings => %w(
|
249
|
-
alternate appendix bookmark cite chapter contents copyright first glossary help icon index
|
250
|
-
last license meta next p3pv1 prev role section stylesheet subsection start top up
|
251
|
-
).inject({}) { |hash, term| hash[term.to_sym] = RDF::XHV[term].to_s; hash },
|
252
|
-
}
|
253
|
-
else
|
254
|
-
{
|
255
|
-
:uri_mappings => {},
|
256
|
-
}
|
257
|
-
end
|
258
|
-
|
259
307
|
# Add prefix definitions from host defaults
|
260
308
|
@host_defaults[:uri_mappings].each_pair do |prefix, value|
|
261
309
|
prefix(prefix, value)
|
262
310
|
end
|
263
311
|
|
264
|
-
add_info(@doc, "version = #{@version}, host_language = #{@host_language}")
|
265
|
-
|
266
312
|
# parse
|
267
313
|
parse_whole_document(@doc, @base_uri)
|
268
314
|
end
|
@@ -319,19 +365,17 @@ module RDF::RDFa
|
|
319
365
|
end
|
320
366
|
|
321
367
|
def add_processor_message(node, message, process_class)
|
322
|
-
puts "#{node_path(node)}: #{message}" if ::RDF::RDFa
|
368
|
+
puts "#{node_path(node)}: #{message}" if ::RDF::RDFa.debug?
|
323
369
|
@debug << "#{node_path(node)}: #{message}" if @debug.is_a?(Array)
|
324
370
|
if @processor_graph
|
325
|
-
@processor_sequence ||= 0
|
326
371
|
n = RDF::Node.new
|
327
372
|
@processor_graph << RDF::Statement.new(n, RDF["type"], process_class)
|
328
373
|
@processor_graph << RDF::Statement.new(n, RDF::DC.description, message)
|
329
374
|
@processor_graph << RDF::Statement.new(n, RDF::DC.date, RDF::Literal::Date.new(DateTime.now))
|
330
|
-
@processor_graph << RDF::Statement.new(n, RDF::RDFA.sequence, RDF::Literal::Integer.new(@processor_sequence += 1))
|
331
375
|
@processor_graph << RDF::Statement.new(n, RDF::RDFA.context, @base_uri)
|
332
376
|
nc = RDF::Node.new
|
333
377
|
@processor_graph << RDF::Statement.new(nc, RDF["type"], RDF::PTR.XPathPointer)
|
334
|
-
@processor_graph << RDF::Statement.new(nc, RDF::PTR.expression, node.path)
|
378
|
+
@processor_graph << RDF::Statement.new(nc, RDF::PTR.expression, node.path) if node.respond_to?(:path)
|
335
379
|
@processor_graph << RDF::Statement.new(n, RDF::RDFA.context, nc)
|
336
380
|
end
|
337
381
|
end
|
@@ -355,9 +399,12 @@ module RDF::RDFa
|
|
355
399
|
def parse_whole_document(doc, base)
|
356
400
|
# find if the document has a base element
|
357
401
|
case @host_language
|
358
|
-
when :
|
402
|
+
when :xhtml1, :xhtml5, :html4, :html5
|
359
403
|
base_el = doc.at_css("html>head>base")
|
360
404
|
base = base_el.attribute("href").to_s.split("#").first if base_el
|
405
|
+
else
|
406
|
+
xml_base = doc.root.attribute_with_ns("base", RDF::XML.to_s)
|
407
|
+
base = xml_base if xml_base
|
361
408
|
end
|
362
409
|
|
363
410
|
if (base)
|
@@ -370,6 +417,18 @@ module RDF::RDFa
|
|
370
417
|
# initialize the evaluation context with the appropriate base
|
371
418
|
evaluation_context = EvaluationContext.new(base, @host_defaults)
|
372
419
|
|
420
|
+
if @version != :"rdfa1.0"
|
421
|
+
# Process default vocabularies
|
422
|
+
process_profile(doc.root, @host_defaults[:profiles]) do |which, value|
|
423
|
+
add_debug(doc.root, "parse_whole_document, #{which}: #{value.inspect}")
|
424
|
+
case which
|
425
|
+
when :uri_mappings then evaluation_context.uri_mappings.merge!(value)
|
426
|
+
when :term_mappings then evaluation_context.term_mappings.merge!(value)
|
427
|
+
when :default_vocabulary then evaluation_context.default_vocabulary = value
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
373
432
|
traverse(doc.root, evaluation_context)
|
374
433
|
add_debug("", "parse_whole_doc: traversal complete'")
|
375
434
|
end
|
@@ -379,7 +438,6 @@ module RDF::RDFa
|
|
379
438
|
# Yields each mapping
|
380
439
|
def process_profile(element, profiles)
|
381
440
|
profiles.
|
382
|
-
reverse.
|
383
441
|
map {|uri| uri(uri).normalize}.
|
384
442
|
each do |uri|
|
385
443
|
# Don't try to open ourselves!
|
@@ -389,10 +447,18 @@ module RDF::RDFa
|
|
389
447
|
end
|
390
448
|
|
391
449
|
old_debug = RDF::RDFa.debug?
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
450
|
+
begin
|
451
|
+
add_info(element, "process_profile: load <#{uri}>")
|
452
|
+
RDF::RDFa.debug = false
|
453
|
+
profile = Profile.find(uri)
|
454
|
+
rescue Exception => e
|
455
|
+
RDF::RDFa.debug = old_debug
|
456
|
+
add_error(element, e.message, RDF::RDFA.ProfileReferenceError)
|
457
|
+
raise # In case we're not in strict mode, we need to be sure processing stops
|
458
|
+
ensure
|
459
|
+
RDF::RDFa.debug = old_debug
|
460
|
+
end
|
461
|
+
|
396
462
|
# Add URI Mappings to prefixes
|
397
463
|
profile.prefixes.each_pair do |prefix, value|
|
398
464
|
prefix(prefix, value)
|
@@ -401,9 +467,6 @@ module RDF::RDFa
|
|
401
467
|
yield :term_mappings, profile.terms unless profile.terms.empty?
|
402
468
|
yield :default_vocabulary, profile.vocabulary if profile.vocabulary
|
403
469
|
end
|
404
|
-
rescue Exception => e
|
405
|
-
add_error(element, e.message, RDF::RDFA.ProfileReferenceError)
|
406
|
-
raise # In case we're not in strict mode, we need to be sure processing stops
|
407
470
|
end
|
408
471
|
|
409
472
|
# Extract the XMLNS mappings from an element
|
@@ -418,7 +481,7 @@ module RDF::RDFa
|
|
418
481
|
next if ns.prefix == "_"
|
419
482
|
|
420
483
|
# Downcase prefix for RDFa 1.1
|
421
|
-
pfx_lc = (@version == :
|
484
|
+
pfx_lc = (@version == :"rdfa1.0" || ns.prefix.nil?) ? ns.prefix : ns.prefix.to_s.downcase
|
422
485
|
if ns.prefix
|
423
486
|
uri_mappings[pfx_lc.to_sym] = ns.href
|
424
487
|
namespaces[pfx_lc] ||= ns.href
|
@@ -432,20 +495,25 @@ module RDF::RDFa
|
|
432
495
|
# Set mappings from @prefix
|
433
496
|
# prefix is a whitespace separated list of prefix-name URI pairs of the form
|
434
497
|
# NCName ':' ' '+ xs:anyURI
|
435
|
-
mappings = element.
|
498
|
+
mappings = element.attribute("prefix").to_s.strip.split(/\s+/)
|
436
499
|
while mappings.length > 0 do
|
437
500
|
prefix, uri = mappings.shift.downcase, mappings.shift
|
438
501
|
#puts "uri_mappings prefix #{prefix} <#{uri}>"
|
439
502
|
next unless prefix.match(/:$/)
|
440
503
|
prefix.chop!
|
441
504
|
|
505
|
+
unless prefix.match(NC_REGEXP)
|
506
|
+
add_error(element, "extract_mappings: Prefix #{prefix.inspect} does not match NCName production")
|
507
|
+
next
|
508
|
+
end
|
509
|
+
|
442
510
|
# A Conforming RDFa Processor must ignore any definition of a mapping for the '_' prefix.
|
443
511
|
next if prefix == "_"
|
444
512
|
|
445
513
|
uri_mappings[prefix.to_s.empty? ? nil : prefix.to_s.to_sym] = uri
|
446
514
|
prefix(prefix, uri)
|
447
515
|
add_info(element, "extract_mappings: prefix #{prefix} => <#{uri}>")
|
448
|
-
end unless @version == :
|
516
|
+
end unless @version == :"rdfa1.0"
|
449
517
|
end
|
450
518
|
|
451
519
|
# The recursive helper function
|
@@ -480,7 +548,7 @@ module RDF::RDFa
|
|
480
548
|
href = attrs['href']
|
481
549
|
vocab = attrs['vocab']
|
482
550
|
xml_base = element.attribute_with_ns("base", RDF::XML.to_s)
|
483
|
-
base = xml_base.to_s if xml_base &&
|
551
|
+
base = xml_base.to_s if xml_base && ![:xhtml1, :xhtml5, :html4, :html5].include?(@host_language)
|
484
552
|
base ||= evaluation_context.base
|
485
553
|
|
486
554
|
# Pull out the attributes needed for the skip test.
|
@@ -512,14 +580,29 @@ module RDF::RDFa
|
|
512
580
|
# Local term mappings [7.5 Steps 2]
|
513
581
|
# Next the current element is parsed for any updates to the local term mappings and local list of URI mappings via @profile.
|
514
582
|
# If @profile is present, its value is processed as defined in RDFa Profiles.
|
515
|
-
unless @version == :
|
583
|
+
unless @version == :"rdfa1.0"
|
516
584
|
begin
|
517
585
|
process_profile(element, profiles) do |which, value|
|
518
586
|
add_debug(element, "[Step 2] traverse, #{which}: #{value.inspect}")
|
519
587
|
case which
|
520
|
-
when :uri_mappings
|
521
|
-
|
522
|
-
|
588
|
+
when :uri_mappings
|
589
|
+
value.each do |k, v|
|
590
|
+
if k.to_s.match(NC_REGEXP)
|
591
|
+
uri_mappings[k] = v
|
592
|
+
else
|
593
|
+
add_error(element, "[Step 2] traverse: Prefix #{k.to_s.inspect} does not match NCName production")
|
594
|
+
end
|
595
|
+
end
|
596
|
+
when :term_mappings
|
597
|
+
value.each do |k, v|
|
598
|
+
if k.to_s.match(NC_REGEXP)
|
599
|
+
term_mappings[k] = v
|
600
|
+
else
|
601
|
+
add_error(element, "[Step 2] traverse: Term #{k.to_s.inspect} does not match NCName production")
|
602
|
+
end
|
603
|
+
end
|
604
|
+
when :default_vocabulary
|
605
|
+
default_vocabulary = value
|
523
606
|
end
|
524
607
|
end
|
525
608
|
rescue
|
@@ -538,12 +621,12 @@ module RDF::RDFa
|
|
538
621
|
unless vocab.nil?
|
539
622
|
default_vocabulary = if vocab.to_s.empty?
|
540
623
|
# Set default_vocabulary to host language default
|
541
|
-
add_debug(element, "[Step
|
624
|
+
add_debug(element, "[Step 3] traverse, reset default_vocaulary to #{@host_defaults.fetch(:vocabulary, nil).inspect}")
|
542
625
|
@host_defaults.fetch(:vocabulary, nil)
|
543
626
|
else
|
544
627
|
uri(vocab)
|
545
628
|
end
|
546
|
-
add_debug(element, "[Step
|
629
|
+
add_debug(element, "[Step 3] traverse, default_vocaulary: #{default_vocabulary.inspect}")
|
547
630
|
end
|
548
631
|
|
549
632
|
# Local term mappings [7.5 Steps 4]
|
@@ -560,8 +643,8 @@ module RDF::RDFa
|
|
560
643
|
language = case
|
561
644
|
when element.at_xpath("@xml:lang", "xml" => RDF::XML["uri"].to_s)
|
562
645
|
element.at_xpath("@xml:lang", "xml" => RDF::XML["uri"].to_s).to_s
|
563
|
-
when element.at_xpath("lang")
|
564
|
-
element.at_xpath("lang").to_s
|
646
|
+
when element.at_xpath("@lang")
|
647
|
+
element.at_xpath("@lang").to_s
|
565
648
|
else
|
566
649
|
language
|
567
650
|
end
|
@@ -605,15 +688,14 @@ module RDF::RDFa
|
|
605
688
|
# otherwise,
|
606
689
|
# if parent object is present, new subject is set to the value of parent object.
|
607
690
|
# Additionally, if @property is not present then the skip element flag is set to 'true';
|
608
|
-
new_subject ||= if
|
691
|
+
new_subject ||= if element == @doc.root && base
|
692
|
+
uri(base)
|
693
|
+
elsif [:xhtml1, :xhtml5, :html4, :html5].include?(@host_language) && element.name =~ /^(head|body)$/
|
609
694
|
# From XHTML+RDFa 1.1:
|
610
695
|
# if no URI is provided, then first check to see if the element is the head or body element.
|
611
696
|
# If it is, then act as if there is an empty @about present, and process it according to the rule for @about.
|
612
697
|
uri(base)
|
613
|
-
elsif
|
614
|
-
# XXX Spec confusion, assume that this is true
|
615
|
-
uri(base)
|
616
|
-
elsif element.attributes['typeof']
|
698
|
+
elsif typeof
|
617
699
|
RDF::Node.new
|
618
700
|
else
|
619
701
|
# if it's null, it's null and nothing changes
|
@@ -633,7 +715,9 @@ module RDF::RDFa
|
|
633
715
|
:restrictions => [:uri])
|
634
716
|
|
635
717
|
# If no URI is provided then the first match from the following rules will apply
|
636
|
-
new_subject ||= if
|
718
|
+
new_subject ||= if element == @doc.root && base
|
719
|
+
uri(base)
|
720
|
+
elsif [:xhtml1, :xhtml5, :html4, :html5].include?(@host_language) && element.name =~ /^(head|body)$/
|
637
721
|
# From XHTML+RDFa 1.1:
|
638
722
|
# if no URI is provided, then first check to see if the element is the head or body element.
|
639
723
|
# If it is, then act as if there is an empty @about present, and process it according to the rule for @about.
|
@@ -674,7 +758,7 @@ module RDF::RDFa
|
|
674
758
|
end
|
675
759
|
|
676
760
|
# Generate triples with given object [Step 9]
|
677
|
-
if current_object_resource
|
761
|
+
if new_subject and current_object_resource
|
678
762
|
rels.each do |r|
|
679
763
|
add_triple(element, new_subject, r, current_object_resource)
|
680
764
|
end
|
@@ -727,7 +811,7 @@ module RDF::RDFa
|
|
727
811
|
# typed literal
|
728
812
|
add_debug(element, "[Step 11] typed literal (#{datatype})")
|
729
813
|
RDF::Literal.new(content || element.inner_text.to_s, :datatype => datatype, :language => language, :validate => validate?, :canonicalize => canonicalize?)
|
730
|
-
elsif @version == :
|
814
|
+
elsif @version == :"rdfa1.1"
|
731
815
|
if datatype.to_s == RDF.XMLLiteral.to_s
|
732
816
|
# XML Literal
|
733
817
|
add_debug(element, "[Step 11(1.1)] XML Literal: #{element.inner_html}")
|
@@ -774,9 +858,9 @@ module RDF::RDFa
|
|
774
858
|
add_error(element, e.message)
|
775
859
|
end
|
776
860
|
|
777
|
-
|
861
|
+
# add each property
|
778
862
|
properties.each do |p|
|
779
|
-
add_triple(element, new_subject, p, current_object_literal)
|
863
|
+
add_triple(element, new_subject, p, current_object_literal) if new_subject
|
780
864
|
end
|
781
865
|
end
|
782
866
|
|
@@ -867,7 +951,7 @@ module RDF::RDFa
|
|
867
951
|
uri = curie_to_resource_or_bnode(element, value, options[:uri_mappings], evaluation_context.parent_subject, restrictions)
|
868
952
|
if uri
|
869
953
|
add_debug(element, "process_uri: #{value} => CURIE => <#{uri}>")
|
870
|
-
elsif @version == :
|
954
|
+
elsif @version == :"rdfa1.0" && value.to_s.match(/^xml/i)
|
871
955
|
# Special case to not allow anything starting with XML to be treated as a URI
|
872
956
|
elsif restrictions.include?(:absuri) || restrictions.include?(:uri)
|
873
957
|
begin
|
@@ -935,22 +1019,14 @@ module RDF::RDFa
|
|
935
1019
|
# As a special case, _: is also a valid reference for one specific bnode.
|
936
1020
|
bnode(reference)
|
937
1021
|
elsif curie.to_s.match(/^:/)
|
938
|
-
add_debug(element, "curie_to_resource_or_bnode: default prefix: defined? #{!!uri_mappings[""]}, defaults: #{@host_defaults[:prefix]}")
|
939
1022
|
# Default prefix
|
940
|
-
|
941
|
-
uri(uri_mappings[nil] + reference.to_s)
|
942
|
-
elsif @host_defaults[:prefix]
|
943
|
-
uri(uri_mappings[@host_defaults[:prefix]] + reference.to_s)
|
944
|
-
else
|
945
|
-
#add_warning(element, "Default namespace prefix is not defined", RDF::RDFA.UnresolvedCURIE)
|
946
|
-
nil
|
947
|
-
end
|
1023
|
+
RDF::XHV[reference.to_s]
|
948
1024
|
elsif !curie.to_s.match(/:/)
|
949
1025
|
# No prefix, undefined (in this context, it is evaluated as a term elsewhere)
|
950
1026
|
nil
|
951
1027
|
else
|
952
1028
|
# Prefixes always downcased
|
953
|
-
prefix = prefix.to_s.downcase unless @version == :
|
1029
|
+
prefix = prefix.to_s.downcase unless @version == :"rdfa1.0"
|
954
1030
|
add_debug(element, "curie_to_resource_or_bnode check for #{prefix.to_s.to_sym.inspect} in #{uri_mappings.inspect}")
|
955
1031
|
ns = uri_mappings[prefix.to_s.to_sym]
|
956
1032
|
if ns
|