rdf-rdfxml 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +2 -0
- data/{History.txt → History.rdoc} +21 -0
- data/README.rdoc +11 -12
- data/Rakefile +11 -19
- data/VERSION +1 -1
- data/lib/rdf/rdfxml.rb +3 -2
- data/lib/rdf/rdfxml/patches/literal_hacks.rb +15 -17
- data/lib/rdf/rdfxml/reader.rb +115 -79
- data/lib/rdf/rdfxml/version.rb +4 -7
- data/lib/rdf/rdfxml/writer.rb +239 -190
- data/rdf-rdfxml.gemspec +14 -20
- data/script/parse +16 -10
- data/script/tc +10 -9
- data/spec/graph_spec.rb +0 -16
- data/spec/literal_spec.rb +2 -3
- data/spec/rdf_helper.rb +6 -6
- data/spec/reader_spec.rb +17 -17
- data/spec/spec_helper.rb +11 -4
- data/spec/writer_spec.rb +384 -331
- metadata +22 -18
- data/lib/rdf/rdfxml/patches/qname_hacks.rb +0 -57
- data/lib/rdf/rdfxml/patches/seq.rb +0 -34
- data/lib/rdf/rdfxml/patches/uri_hacks.rb +0 -24
- data/spec/uri_spec.rb +0 -115
data/.yardopts
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
=== 0.3.0
|
2
|
+
* RDF.rb 0.3.0 compatibility updates
|
3
|
+
* Remove literal_normalization and qname_hacks, add back uri_hacks (until 0.3.0)
|
4
|
+
* Use nil for default namespace
|
5
|
+
* In Writer
|
6
|
+
* Use only :prefixes for creating QNames.
|
7
|
+
* Add :standard_prefixes and :default_namespace options.
|
8
|
+
* Improve Writer#to_qname.
|
9
|
+
* Don't try to translate rdf:_1 to rdf:li due to complex corner cases.
|
10
|
+
* Fix problems with XMLLiteral, rdf:type and rdf:nodeID serialization.
|
11
|
+
* In Reader
|
12
|
+
* URI canonicalization and validation.
|
13
|
+
* Added :canonicalize, and :intern options.
|
14
|
+
* Change :strict option to :validate.
|
15
|
+
* Don't create unnecessary namespaces.
|
16
|
+
* Don't use regexp to substitute base URI in URI serialization.
|
17
|
+
* Collect prefixes when extracting mappings.
|
18
|
+
* Literal::XML
|
19
|
+
* Add all in-scope namespaces, not just those that seem to be used.
|
20
|
+
* RSpec 2 compatibility
|
21
|
+
|
1
22
|
=== 0.2.3
|
2
23
|
* Fixed QName generation in Writer based on RDF/XML Processing recommendations
|
3
24
|
|
data/README.rdoc
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
RDF/XML parser for RDF.rb.
|
4
4
|
|
5
|
-
== DESCRIPTION
|
5
|
+
== DESCRIPTION
|
6
6
|
|
7
7
|
RDF::RDFXML is an RDF/XML reader/writer for Ruby using the RDF.rb library suite.
|
8
8
|
|
9
|
-
== FEATURES
|
10
|
-
RDF::RDFXML parses RDF/XML into statements or triples.
|
9
|
+
== FEATURES
|
10
|
+
RDF::RDFXML parses RDF/XML into statements or triples and serializes triples, statements or graphs.
|
11
11
|
|
12
|
-
* Fully compliant RDF/XML parser.
|
12
|
+
* Fully compliant RDF/XML parser and serializer.
|
13
13
|
|
14
14
|
Install with 'gem install rdf-rdfxml'
|
15
15
|
|
@@ -23,7 +23,7 @@ Instantiate a parser and parse source, specifying type and base-URL
|
|
23
23
|
end
|
24
24
|
|
25
25
|
== Dependencies
|
26
|
-
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.
|
26
|
+
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.3.0)
|
27
27
|
* [Nokogiri](http://rubygems.org/gems/nokogiri) (>= 1.3.3)
|
28
28
|
|
29
29
|
== TODO
|
@@ -31,20 +31,20 @@ Instantiate a parser and parse source, specifying type and base-URL
|
|
31
31
|
* Consider a SAX-based parser for improved performance
|
32
32
|
* Add generic RDF/XML Writer
|
33
33
|
|
34
|
-
== Resources
|
34
|
+
== Resources
|
35
35
|
* Distiller[http://kellogg-assoc/distiller]
|
36
36
|
* RDoc[http://rdoc.info/projects/gkellogg/rdf-rdfxml]
|
37
37
|
* History[http://github.com/gkellogg/rdf-rdfxml/blob/master/History.txt]
|
38
38
|
* "XHTML+RDFXML 1.1 Core"[http://www.w3.org/TR/2010/WD-xhtml-rdfa-20100422/]
|
39
39
|
* "RDF Tests"[http://www.w3.org/2000/10/rdf-tests/rdfcore/allTestCases.html]
|
40
40
|
|
41
|
-
== AUTHOR
|
41
|
+
== AUTHOR
|
42
42
|
* Gregg Kellogg <gregg@kellogg-assoc.com>
|
43
43
|
|
44
|
-
== CONTRIBUTORS
|
44
|
+
== CONTRIBUTORS
|
45
45
|
* Nicholas Humfrey <nicholas.humfrey@bbc.co.uk>
|
46
46
|
|
47
|
-
== LICENSE
|
47
|
+
== LICENSE
|
48
48
|
|
49
49
|
(The MIT License)
|
50
50
|
|
@@ -72,7 +72,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
72
72
|
== FEEDBACK
|
73
73
|
|
74
74
|
* gregg@kellogg-assoc.com
|
75
|
-
* rubygems.org/rdf-rdfxml
|
76
|
-
* github.com/gkellogg/rdf-rdfxml
|
77
|
-
* gkellogg.lighthouseapp.com for bug reports
|
75
|
+
* http://rubygems.org/rdf-rdfxml
|
76
|
+
* http://github.com/gkellogg/rdf-rdfxml
|
78
77
|
* public-rdf-ruby mailing list on w3.org
|
data/Rakefile
CHANGED
@@ -7,43 +7,35 @@ begin
|
|
7
7
|
Jeweler::Tasks.new do |gemspec|
|
8
8
|
gemspec.name = "rdf-rdfxml"
|
9
9
|
gemspec.summary = "RDF/XML reader/writer for RDF.rb."
|
10
|
-
gemspec.description =
|
11
|
-
RDF::RDFXML is an RDF/XML reader and writer for Ruby using the RDF.rb library suite.
|
12
|
-
DESCRIPTION
|
10
|
+
gemspec.description = %q(RDF::RDFXML is an RDF/XML reader and writer for Ruby using the RDF.rb library suite.)
|
13
11
|
gemspec.email = "gregg@kellogg-assoc.com"
|
14
12
|
gemspec.homepage = "http://github.com/gkellogg/rdf-rdfxml"
|
15
13
|
gemspec.authors = ["Gregg Kellogg"]
|
16
|
-
gemspec.add_dependency('rdf', '>= 0.
|
14
|
+
gemspec.add_dependency('rdf', '>= 0.3.0')
|
17
15
|
gemspec.add_dependency('nokogiri', '>= 1.3.3')
|
18
|
-
gemspec.add_development_dependency('rspec')
|
19
|
-
gemspec.add_development_dependency('rdf-spec'
|
16
|
+
gemspec.add_development_dependency('rspec', '>= 2.1.0')
|
17
|
+
gemspec.add_development_dependency('rdf-spec')
|
20
18
|
gemspec.add_development_dependency('rdf-isomorphic')
|
21
19
|
gemspec.add_development_dependency('yard')
|
22
|
-
gemspec.extra_rdoc_files = %w(README.rdoc History.
|
20
|
+
gemspec.extra_rdoc_files = %w(README.rdoc History.rdoc AUTHORS CONTRIBUTORS)
|
23
21
|
end
|
24
22
|
Jeweler::GemcutterTasks.new
|
25
23
|
rescue LoadError
|
26
24
|
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
27
25
|
end
|
28
26
|
|
29
|
-
require '
|
30
|
-
|
31
|
-
spec.libs << 'lib' << 'spec'
|
32
|
-
spec.spec_files = FileList['spec/*_spec.rb']
|
33
|
-
end
|
27
|
+
require 'rspec/core/rake_task'
|
28
|
+
RSpec::Core::RakeTask.new(:spec)
|
34
29
|
|
35
30
|
desc "Run specs through RCov"
|
36
|
-
|
37
|
-
spec.libs << 'lib' << 'spec'
|
38
|
-
spec.pattern = 'spec/*_spec.rb'
|
31
|
+
RSpec::Core::RakeTask.new("spec:rcov") do |spec|
|
39
32
|
spec.rcov = true
|
33
|
+
spec.rcov_opts = %q[--exclude "spec"]
|
40
34
|
end
|
41
35
|
|
42
36
|
desc "Generate HTML report specs"
|
43
|
-
|
44
|
-
spec.
|
45
|
-
spec.spec_files = FileList['spec/*_spec.rb']
|
46
|
-
spec.spec_opts = ["--format", "html:doc/spec.html"]
|
37
|
+
RSpec::Core::RakeTask.new("doc:spec") do |spec|
|
38
|
+
spec.rspec_opts = ["--format", "html", "-o", "doc/spec.html"]
|
47
39
|
end
|
48
40
|
|
49
41
|
YARD::Rake::YardocTask.new do |t|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/rdf/rdfxml.rb
CHANGED
@@ -25,11 +25,12 @@ module RDF
|
|
25
25
|
require 'rdf/rdfxml/patches/array_hacks'
|
26
26
|
require 'rdf/rdfxml/patches/literal_hacks'
|
27
27
|
require 'rdf/rdfxml/patches/nokogiri_hacks'
|
28
|
-
require 'rdf/rdfxml/patches/qname_hacks'
|
29
|
-
require 'rdf/rdfxml/patches/uri_hacks'
|
30
28
|
autoload :Reader, 'rdf/rdfxml/reader'
|
31
29
|
autoload :Writer, 'rdf/rdfxml/writer'
|
32
30
|
autoload :VERSION, 'rdf/rdfxml/version'
|
33
31
|
autoload :XML, 'rdf/rdfxml/vocab'
|
32
|
+
|
33
|
+
def self.debug?; @debug; end
|
34
|
+
def self.debug=(value); @debug = value; end
|
34
35
|
end
|
35
36
|
end
|
@@ -20,7 +20,7 @@ module RDF; class Literal
|
|
20
20
|
##
|
21
21
|
# @param [Object] value
|
22
22
|
# @option options [String] :lexical (nil)
|
23
|
-
# @option options [Hash] :namespaces ({}) Use
|
23
|
+
# @option options [Hash] :namespaces ({}) Use "" to declare default namespace
|
24
24
|
# @option options [Symbol] :language (nil)
|
25
25
|
# @option options [:nokogiri, :libxml, or :rexml] :library
|
26
26
|
def initialize(value, options = {})
|
@@ -68,17 +68,15 @@ module RDF; class Literal
|
|
68
68
|
def parse_value(value, options)
|
69
69
|
ns_hash = {}
|
70
70
|
options[:namespaces].each_pair do |prefix, uri|
|
71
|
-
prefix = prefix
|
71
|
+
prefix = prefix.to_s
|
72
72
|
attr = prefix.empty? ? "xmlns" : "xmlns:#{prefix}"
|
73
73
|
ns_hash[attr] = uri.to_s
|
74
74
|
end
|
75
|
-
ns_strs = []
|
76
|
-
ns_hash.each_pair {|a, u| ns_strs << "#{a}=\"#{u}\""}
|
77
75
|
|
78
76
|
case @library
|
79
|
-
when :nokogiri then parse_value_nokogiri(value,
|
80
|
-
when :libxml then parse_value_libxml(value,
|
81
|
-
when :rexml then parse_value_rexml(value,
|
77
|
+
when :nokogiri then parse_value_nokogiri(value, ns_hash, options)
|
78
|
+
when :libxml then parse_value_libxml(value, ns_hash, options)
|
79
|
+
when :rexml then parse_value_rexml(value, ns_hash, options)
|
82
80
|
else value.to_s
|
83
81
|
end
|
84
82
|
end
|
@@ -99,10 +97,12 @@ module RDF; class Literal
|
|
99
97
|
# to the required element, and does not properly order either namespaces or attributes.
|
100
98
|
#
|
101
99
|
# An open-issue in Nokogiri is to add support for C14N from the underlying libxml2 libraries.
|
102
|
-
def parse_value_nokogiri(value,
|
100
|
+
def parse_value_nokogiri(value, ns_hash, options)
|
103
101
|
elements = if value.is_a?(Nokogiri::XML::NodeSet)
|
104
102
|
value
|
105
103
|
else
|
104
|
+
ns_strs = []
|
105
|
+
ns_hash.each_pair {|a, u| ns_strs << "#{a}=\"#{u}\""}
|
106
106
|
# Add inherited namespaces to created root element so that they're inherited to sub-elements
|
107
107
|
Nokogiri::XML::Document.parse("<foo #{ns_strs.join(" ")}>#{value.to_s}</foo>").root.children
|
108
108
|
end
|
@@ -110,17 +110,15 @@ module RDF; class Literal
|
|
110
110
|
elements.map do |c|
|
111
111
|
if c.is_a?(Nokogiri::XML::Element)
|
112
112
|
c = Nokogiri::XML.parse(c.dup.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS)).root
|
113
|
-
# Gather namespaces from self and decendant nodes
|
114
|
-
c.traverse do |n|
|
115
|
-
ns = n.namespace
|
116
|
-
next unless ns
|
117
|
-
prefix = ns.prefix ? "xmlns:#{ns.prefix}" : "xmlns"
|
118
|
-
c[prefix] = ns.href.to_s unless c.namespaces[prefix]
|
119
|
-
end
|
120
113
|
|
114
|
+
# Apply defined namespaces
|
115
|
+
ns_hash.each_pair do |prefix, href|
|
116
|
+
c[prefix] = href unless c.namespaces[prefix]
|
117
|
+
end
|
118
|
+
|
121
119
|
# Add language
|
122
|
-
if language && c["lang"].to_s.empty?
|
123
|
-
c["xml:lang"] = language.to_s
|
120
|
+
if options[:language] && c["lang"].to_s.empty?
|
121
|
+
c["xml:lang"] = options[:language].to_s
|
124
122
|
end
|
125
123
|
end
|
126
124
|
c
|
data/lib/rdf/rdfxml/reader.rb
CHANGED
@@ -4,6 +4,8 @@ module RDF::RDFXML
|
|
4
4
|
##
|
5
5
|
# An RDF/XML parser in Ruby
|
6
6
|
#
|
7
|
+
# Based on RDF/XML Syntax Specification: http://www.w3.org/TR/REC-rdf-syntax/
|
8
|
+
#
|
7
9
|
# @author [Gregg Kellogg](http://kellogg-assoc.com/)
|
8
10
|
class Reader < RDF::Reader
|
9
11
|
format Format
|
@@ -33,7 +35,7 @@ module RDF::RDFXML
|
|
33
35
|
attr :graph, true
|
34
36
|
attr :li_counter, true
|
35
37
|
|
36
|
-
def initialize(base, element, graph)
|
38
|
+
def initialize(base, element, graph, &cb)
|
37
39
|
# Initialize the evaluation context, [5.1]
|
38
40
|
self.base = RDF::URI.intern(base)
|
39
41
|
@uri_mappings = {}
|
@@ -41,51 +43,52 @@ module RDF::RDFXML
|
|
41
43
|
@graph = graph
|
42
44
|
@li_counter = 0
|
43
45
|
|
44
|
-
extract_from_element(element) if element
|
46
|
+
extract_from_element(element, &cb) if element
|
45
47
|
end
|
46
48
|
|
47
49
|
# Clone existing evaluation context adding information from element
|
48
|
-
def clone(element, options = {})
|
50
|
+
def clone(element, options = {}, &cb)
|
49
51
|
new_ec = EvaluationContext.new(@base, nil, @graph)
|
50
52
|
new_ec.uri_mappings = self.uri_mappings.clone
|
51
53
|
new_ec.language = self.language
|
52
54
|
|
53
|
-
new_ec.extract_from_element(element) if element
|
55
|
+
new_ec.extract_from_element(element, &cb) if element
|
54
56
|
|
55
57
|
options.each_pair {|k, v| new_ec.send("#{k}=", v)}
|
56
58
|
new_ec
|
57
59
|
end
|
58
60
|
|
59
61
|
# Extract Evaluation Context from an element by looking at ancestors recurively
|
60
|
-
def extract_from_ancestors(el)
|
62
|
+
def extract_from_ancestors(el, &cb)
|
61
63
|
ancestors = el.ancestors
|
62
64
|
while ancestors.length > 0
|
63
65
|
a = ancestors.pop
|
64
66
|
next unless a.element?
|
65
|
-
extract_from_element(a)
|
67
|
+
extract_from_element(a, &cb)
|
66
68
|
end
|
67
|
-
extract_from_element(el)
|
69
|
+
extract_from_element(el, &cb)
|
68
70
|
end
|
69
71
|
|
70
72
|
# Extract Evaluation Context from an element
|
71
|
-
def extract_from_element(el)
|
73
|
+
def extract_from_element(el, &cb)
|
72
74
|
b = el.attribute_with_ns("base", RDF::XML.to_s)
|
73
75
|
lang = el.attribute_with_ns("lang", RDF::XML.to_s)
|
74
76
|
self.base = self.base.join(b) if b
|
75
77
|
self.language = lang if lang
|
76
|
-
self.uri_mappings.merge!(extract_mappings(el))
|
78
|
+
self.uri_mappings.merge!(extract_mappings(el, &cb))
|
77
79
|
end
|
78
80
|
|
79
81
|
# Extract the XMLNS mappings from an element
|
80
|
-
def extract_mappings(element)
|
82
|
+
def extract_mappings(element, &cb)
|
81
83
|
mappings = {}
|
82
84
|
|
83
85
|
# look for xmlns
|
84
86
|
element.namespaces.each do |attr_name,attr_value|
|
85
|
-
abbr,
|
87
|
+
abbr, prefix = attr_name.to_s.split(":")
|
86
88
|
if abbr == "xmlns"
|
87
89
|
attr_value = self.base.to_s + attr_value if attr_value.match(/^\#/)
|
88
|
-
mappings[
|
90
|
+
mappings[prefix] = attr_value
|
91
|
+
cb.call(prefix, attr_value) if block_given?
|
89
92
|
end
|
90
93
|
end
|
91
94
|
mappings
|
@@ -99,8 +102,9 @@ module RDF::RDFXML
|
|
99
102
|
|
100
103
|
# Set XML base. Ignore any fragment
|
101
104
|
def base=(b)
|
102
|
-
|
103
|
-
|
105
|
+
base = Addressable::URI.parse(b)
|
106
|
+
base.fragment = nil
|
107
|
+
@base = RDF::URI.intern(base)
|
104
108
|
end
|
105
109
|
|
106
110
|
def inspect
|
@@ -113,29 +117,41 @@ module RDF::RDFXML
|
|
113
117
|
##
|
114
118
|
# Initializes the RDF/XML reader instance.
|
115
119
|
#
|
116
|
-
# @param [IO, File, String]
|
117
|
-
#
|
118
|
-
# @
|
119
|
-
#
|
120
|
+
# @param [Nokogiri::XML::Document, IO, File, String] input
|
121
|
+
# the input stream to read
|
122
|
+
# @param [Hash{Symbol => Object}] options
|
123
|
+
# any additional options
|
124
|
+
# @option options [Encoding] :encoding (Encoding::UTF_8)
|
125
|
+
# the encoding of the input stream (Ruby 1.9+)
|
126
|
+
# @option options [Boolean] :validate (false)
|
127
|
+
# whether to validate the parsed statements and values
|
128
|
+
# @option options [Boolean] :canonicalize (false)
|
129
|
+
# whether to canonicalize parsed literals
|
130
|
+
# @option options [Boolean] :intern (true)
|
131
|
+
# whether to intern all parsed URIs
|
132
|
+
# @option options [Hash] :prefixes (Hash.new)
|
133
|
+
# the prefix mappings to use (not supported by all readers)
|
134
|
+
# @option options [#to_s] :base_uri (nil)
|
135
|
+
# the base URI to use when resolving relative URIs
|
136
|
+
# @option options [Array] :debug
|
137
|
+
# Array to place debug messages
|
120
138
|
# @return [reader]
|
121
|
-
# @yield [reader]
|
122
|
-
# @yieldparam
|
123
|
-
# @
|
139
|
+
# @yield [reader] `self`
|
140
|
+
# @yieldparam [RDF::Reader] reader
|
141
|
+
# @yieldreturn [void] ignored
|
142
|
+
# @raise [Error]:: Raises RDF::ReaderError if _validate_
|
124
143
|
def initialize(input = $stdin, options = {}, &block)
|
125
144
|
super do
|
126
145
|
@debug = options[:debug]
|
127
|
-
@
|
128
|
-
@base_uri = RDF::URI.intern(options[:base_uri])
|
146
|
+
@base_uri = uri(options[:base_uri]) if options[:base_uri]
|
129
147
|
|
130
|
-
@id_mapping = Hash.new
|
131
|
-
|
132
148
|
@doc = case input
|
133
149
|
when Nokogiri::XML::Document then input
|
134
150
|
else Nokogiri::XML.parse(input, @base_uri.to_s)
|
135
151
|
end
|
136
152
|
|
137
|
-
raise RDF::ReaderError, "Synax errors:\n#{@doc.errors}" if !@doc.errors.empty? &&
|
138
|
-
raise RDF::ReaderError, "Empty document" if (@doc.nil? || @doc.root.nil?) &&
|
153
|
+
raise RDF::ReaderError, "Synax errors:\n#{@doc.errors}" if !@doc.errors.empty? && validate?
|
154
|
+
raise RDF::ReaderError, "Empty document" if (@doc.nil? || @doc.root.nil?) && validate?
|
139
155
|
|
140
156
|
block.call(self) if block_given?
|
141
157
|
end
|
@@ -165,18 +181,25 @@ module RDF::RDFXML
|
|
165
181
|
if rdf_nodes.length == 0
|
166
182
|
# If none found, root element may be processed as an RDF Node
|
167
183
|
|
168
|
-
ec = EvaluationContext.new(@base_uri, root, @graph)
|
184
|
+
ec = EvaluationContext.new(@base_uri, root, @graph) do |prefix, value|
|
185
|
+
prefix(prefix, value)
|
186
|
+
end
|
187
|
+
|
169
188
|
nodeElement(root, ec)
|
170
189
|
else
|
171
190
|
rdf_nodes.each do |node|
|
172
191
|
# XXX Skip this element if it's contained within another rdf:RDF element
|
173
192
|
|
174
193
|
# Extract base, lang and namespaces from parents to create proper evaluation context
|
175
|
-
ec = EvaluationContext.new(@base_uri, nil, @graph)
|
194
|
+
ec = EvaluationContext.new(@base_uri, nil, @graph) do |prefix, value|
|
195
|
+
prefix(prefix, value)
|
196
|
+
end
|
176
197
|
ec.extract_from_ancestors(node)
|
177
198
|
node.children.each {|el|
|
178
199
|
next unless el.elem?
|
179
|
-
new_ec = ec.clone(el)
|
200
|
+
new_ec = ec.clone(el) do |prefix, value|
|
201
|
+
prefix(prefix, value)
|
202
|
+
end
|
180
203
|
nodeElement(el, new_ec)
|
181
204
|
}
|
182
205
|
end
|
@@ -218,7 +241,7 @@ module RDF::RDFXML
|
|
218
241
|
# @param [XML Node, any] node:: XML Node or string for showing context
|
219
242
|
# @param [String] message::
|
220
243
|
def add_debug(node, message)
|
221
|
-
puts "#{node_path(node)}: #{message}" if
|
244
|
+
puts "#{node_path(node)}: #{message}" if ::RDF::RDFXML::debug?
|
222
245
|
@debug << "#{node_path(node)}: #{message}" if @debug.is_a?(Array)
|
223
246
|
end
|
224
247
|
|
@@ -229,7 +252,7 @@ module RDF::RDFXML
|
|
229
252
|
# @param [URI] predicate:: the predicate of the statement
|
230
253
|
# @param [URI, BNode, Literal] object:: the object of the statement
|
231
254
|
# @return [Statement]:: Added statement
|
232
|
-
# @raise [RDF::ReaderError]:: Checks parameter types and raises if they are incorrect if
|
255
|
+
# @raise [RDF::ReaderError]:: Checks parameter types and raises if they are incorrect if validating.
|
233
256
|
def add_triple(node, subject, predicate, object)
|
234
257
|
statement = RDF::Statement.new(subject, predicate, object)
|
235
258
|
add_debug(node, "statement: #{statement}")
|
@@ -241,7 +264,7 @@ module RDF::RDFXML
|
|
241
264
|
# @param [XML Element] el:: XMl Element to parse
|
242
265
|
# @param [EvaluationContext] ec:: Evaluation context
|
243
266
|
# @return [RDF::URI] subject:: The subject found for the node
|
244
|
-
# @raise [RDF::ReaderError]:: Raises Exception if
|
267
|
+
# @raise [RDF::ReaderError]:: Raises Exception if validating
|
245
268
|
def nodeElement(el, ec)
|
246
269
|
# subject
|
247
270
|
subject = ec.subject || parse_subject(el, ec)
|
@@ -266,7 +289,7 @@ module RDF::RDFXML
|
|
266
289
|
elsif is_propertyAttr?(attr)
|
267
290
|
# Attributes not RDF.type
|
268
291
|
predicate = attr.uri
|
269
|
-
lit = RDF::Literal.new(attr.value, :language => ec.language)
|
292
|
+
lit = RDF::Literal.new(attr.value, :language => ec.language, :validate => validate?, :canonicalize => canonicalize?)
|
270
293
|
add_triple(attr, subject, predicate, lit)
|
271
294
|
end
|
272
295
|
end
|
@@ -275,7 +298,9 @@ module RDF::RDFXML
|
|
275
298
|
li_counter = 0 # this will increase for each li we iterate through
|
276
299
|
el.children.each do |child|
|
277
300
|
next unless child.elem?
|
278
|
-
child_ec = ec.clone(child)
|
301
|
+
child_ec = ec.clone(child) do |prefix, value|
|
302
|
+
prefix(prefix, value)
|
303
|
+
end
|
279
304
|
predicate = child.uri
|
280
305
|
add_debug(child, "propertyElt, predicate: #{predicate}")
|
281
306
|
propertyElementURI_check(child)
|
@@ -330,13 +355,13 @@ module RDF::RDFXML
|
|
330
355
|
|
331
356
|
if nodeID && resourceAttr
|
332
357
|
add_debug(el, "Cannot have rdf:nodeID and rdf:resource.")
|
333
|
-
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:resource.") if
|
358
|
+
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:resource.") if validate?
|
334
359
|
end
|
335
360
|
|
336
361
|
# Apply character transformations
|
337
|
-
id = id_check(el, RDF::NTriples.
|
338
|
-
resourceAttr = RDF::NTriples.
|
339
|
-
nodeID = nodeID_check(el, RDF::NTriples.
|
362
|
+
id = id_check(el, RDF::NTriples.unescape(id), nil) if id
|
363
|
+
resourceAttr = RDF::NTriples.unescape(resourceAttr) if resourceAttr
|
364
|
+
nodeID = nodeID_check(el, RDF::NTriples.unescape(nodeID)) if nodeID
|
340
365
|
|
341
366
|
add_debug(child, "attrs: #{attrs.inspect}")
|
342
367
|
add_debug(child, "datatype: #{datatype}") if datatype
|
@@ -348,7 +373,9 @@ module RDF::RDFXML
|
|
348
373
|
if attrs.empty? && datatype.nil? && parseType.nil? && element_nodes.length == 1
|
349
374
|
# Production resourcePropertyElt
|
350
375
|
|
351
|
-
new_ec = child_ec.clone(nil)
|
376
|
+
new_ec = child_ec.clone(nil) do |prefix, value|
|
377
|
+
prefix(prefix, value)
|
378
|
+
end
|
352
379
|
new_node_element = element_nodes.first
|
353
380
|
add_debug(child, "resourcePropertyElt: #{node_path(new_node_element)}")
|
354
381
|
new_subject = nodeElement(new_node_element, new_ec)
|
@@ -357,9 +384,9 @@ module RDF::RDFXML
|
|
357
384
|
# Production literalPropertyElt
|
358
385
|
add_debug(child, "literalPropertyElt")
|
359
386
|
|
360
|
-
literal_opts = {}
|
387
|
+
literal_opts = {:validate => validate?, :canonicalize => canonicalize?}
|
361
388
|
if datatype
|
362
|
-
literal_opts[:datatype] =
|
389
|
+
literal_opts[:datatype] = uri(datatype)
|
363
390
|
else
|
364
391
|
literal_opts[:language] = child_ec.language
|
365
392
|
end
|
@@ -373,7 +400,7 @@ module RDF::RDFXML
|
|
373
400
|
unless attrs.empty?
|
374
401
|
warn = "Resource Property with extra attributes: '#{attrs.inspect}'"
|
375
402
|
add_debug(child, warn)
|
376
|
-
raise RDF::ReaderError.new(warn) if
|
403
|
+
raise RDF::ReaderError.new(warn) if validate?
|
377
404
|
end
|
378
405
|
|
379
406
|
# For element e with possibly empty element content c.
|
@@ -396,7 +423,9 @@ module RDF::RDFXML
|
|
396
423
|
node.namespace = pt_attr.namespace
|
397
424
|
node.attributes.keys.each {|a| node.remove_attribute(a)}
|
398
425
|
node.node_name = "Description"
|
399
|
-
new_ec = child_ec.clone(nil, :subject => n)
|
426
|
+
new_ec = child_ec.clone(nil, :subject => n) do |prefix, value|
|
427
|
+
prefix(prefix, value)
|
428
|
+
end
|
400
429
|
nodeElement(node, new_ec)
|
401
430
|
elsif parseType == "Collection"
|
402
431
|
# Production parseTypeCollectionPropertyElt
|
@@ -405,7 +434,7 @@ module RDF::RDFXML
|
|
405
434
|
unless attrs.empty?
|
406
435
|
warn = "Resource Property with extra attributes: '#{attrs.inspect}'"
|
407
436
|
add_debug(child, warn)
|
408
|
-
raise RDF::ReaderError.new(warn) if
|
437
|
+
raise RDF::ReaderError.new(warn) if validate?
|
409
438
|
end
|
410
439
|
|
411
440
|
# For element event e with possibly empty nodeElementList l. Set s:=list().
|
@@ -421,7 +450,9 @@ module RDF::RDFXML
|
|
421
450
|
o = s[i+1]
|
422
451
|
f = element_nodes[i]
|
423
452
|
|
424
|
-
new_ec = child_ec.clone(nil)
|
453
|
+
new_ec = child_ec.clone(nil) do |prefix, value|
|
454
|
+
prefix(prefix, value)
|
455
|
+
end
|
425
456
|
object = nodeElement(f, new_ec)
|
426
457
|
add_triple(child, n, RDF.first, object)
|
427
458
|
add_triple(child, n, RDF.rest, o ? o : RDF.nil)
|
@@ -433,13 +464,13 @@ module RDF::RDFXML
|
|
433
464
|
unless attrs.empty?
|
434
465
|
warn = "Resource Property with extra attributes: '#{attrs.inspect}'"
|
435
466
|
add_debug(child, warn)
|
436
|
-
raise RDF::ReaderError.new(warn) if
|
467
|
+
raise RDF::ReaderError.new(warn) if validate?
|
437
468
|
end
|
438
469
|
|
439
470
|
if resourceAttr
|
440
471
|
warn = "illegal rdf:resource"
|
441
472
|
add_debug(child, warn)
|
442
|
-
raise RDF::ReaderError.new(warn) if
|
473
|
+
raise RDF::ReaderError.new(warn) if validate?
|
443
474
|
end
|
444
475
|
|
445
476
|
object = RDF::Literal.new(child.children, :datatype => RDF.XMLLiteral, :namespaces => child_ec.uri_mappings, :language => ec.language)
|
@@ -512,23 +543,23 @@ module RDF::RDFXML
|
|
512
543
|
|
513
544
|
if nodeID && about
|
514
545
|
add_debug(el, "Cannot have rdf:nodeID and rdf:about.")
|
515
|
-
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:about.") if
|
546
|
+
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:about.") if validate?
|
516
547
|
elsif nodeID && id
|
517
548
|
add_debug(el, "Cannot have rdf:nodeID and rdf:ID.")
|
518
|
-
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:ID.") if
|
549
|
+
raise RDF::ReaderError.new("Cannot have rdf:nodeID and rdf:ID.") if validate?
|
519
550
|
end
|
520
551
|
|
521
552
|
case
|
522
553
|
when id
|
523
|
-
add_debug(el, "parse_subject, id: '#{RDF::NTriples.
|
524
|
-
id_check(el, RDF::NTriples.
|
554
|
+
add_debug(el, "parse_subject, id: '#{RDF::NTriples.unescape(id.value)}'")
|
555
|
+
id_check(el, RDF::NTriples.unescape(id.value), ec.base) # Returns URI
|
525
556
|
when nodeID
|
526
557
|
# The value of rdf:nodeID must match the XML Name production
|
527
|
-
nodeID = nodeID_check(el, RDF::NTriples.
|
558
|
+
nodeID = nodeID_check(el, RDF::NTriples.unescape(nodeID.value))
|
528
559
|
add_debug(el, "parse_subject, nodeID: '#{nodeID}")
|
529
560
|
bnode(nodeID)
|
530
561
|
when about
|
531
|
-
about = RDF::NTriples.
|
562
|
+
about = RDF::NTriples.unescape(about.value)
|
532
563
|
add_debug(el, "parse_subject, about: '#{about}'")
|
533
564
|
ec.base.join(about)
|
534
565
|
else
|
@@ -539,28 +570,24 @@ module RDF::RDFXML
|
|
539
570
|
|
540
571
|
# ID attribute must be an NCName
|
541
572
|
def id_check(el, id, base)
|
542
|
-
|
543
|
-
# ID may only be specified once for the same URI
|
544
|
-
if base
|
545
|
-
# FIXME: Known bug in RDF::URI#join
|
546
|
-
uri = base.join("##{id}")
|
547
|
-
if @id_mapping[id] && @id_mapping[id] == uri
|
548
|
-
warn = "ID addtribute '#{id}' may only be defined once for the same URI"
|
549
|
-
add_debug(el, warn)
|
550
|
-
raise RDF::ReaderError.new(warn) if @strict
|
551
|
-
end
|
552
|
-
|
553
|
-
@id_mapping[id] = uri
|
554
|
-
# Returns URI, in this case
|
555
|
-
else
|
556
|
-
id
|
557
|
-
end
|
558
|
-
else
|
573
|
+
unless NC_REGEXP.match(id)
|
559
574
|
warn = "ID addtribute '#{id}' must be a NCName"
|
560
|
-
add_debug(el, "ID addtribute '#{id}' must be a NCName")
|
561
575
|
add_debug(el, warn)
|
562
|
-
raise RDF::ReaderError.new(warn) if
|
563
|
-
|
576
|
+
raise RDF::ReaderError.new(warn) if validate?
|
577
|
+
end
|
578
|
+
# ID may only be specified once for the same URI
|
579
|
+
if base
|
580
|
+
uri = uri(base, "##{id}")
|
581
|
+
if prefix(id) && RDF::URI(prefix(id)) == uri
|
582
|
+
warn = "ID addtribute '#{id}' may only be defined once for the same URI"
|
583
|
+
add_debug(el, warn)
|
584
|
+
raise RDF::ReaderError.new(warn) if validate?
|
585
|
+
end
|
586
|
+
|
587
|
+
RDF::URI(prefix(id, uri))
|
588
|
+
# Returns URI, in this case
|
589
|
+
else
|
590
|
+
id
|
564
591
|
end
|
565
592
|
end
|
566
593
|
|
@@ -571,7 +598,7 @@ module RDF::RDFXML
|
|
571
598
|
nodeID
|
572
599
|
else
|
573
600
|
add_debug(el, "nodeID addtribute '#{nodeID}' must be an XML Name")
|
574
|
-
raise RDF::ReaderError.new("nodeID addtribute '#{nodeID}' must be a NCName") if
|
601
|
+
raise RDF::ReaderError.new("nodeID addtribute '#{nodeID}' must be a NCName") if validate?
|
575
602
|
nil
|
576
603
|
end
|
577
604
|
end
|
@@ -581,7 +608,7 @@ module RDF::RDFXML
|
|
581
608
|
if ([RDF.Description.to_s, RDF.li.to_s] + OLD_TERMS).include?(attr.uri.to_s)
|
582
609
|
warn = "Invalid use of rdf:#{attr.name}"
|
583
610
|
add_debug(attr, warn)
|
584
|
-
raise RDF::ReaderError.new(warn) if
|
611
|
+
raise RDF::ReaderError.new(warn) if validate?
|
585
612
|
return false
|
586
613
|
end
|
587
614
|
!CORE_SYNTAX_TERMS.include?(attr.uri.to_s) && attr.namespace && attr.namespace.href != RDF::XML.to_s
|
@@ -592,7 +619,7 @@ module RDF::RDFXML
|
|
592
619
|
if (CORE_SYNTAX_TERMS + [RDF.li.to_s] + OLD_TERMS).include?(el.uri.to_s)
|
593
620
|
warn = "Invalid use of rdf:#{el.name}"
|
594
621
|
add_debug(el, warn)
|
595
|
-
raise RDF::ReaderError.new(warn) if
|
622
|
+
raise RDF::ReaderError.new(warn) if validate?
|
596
623
|
end
|
597
624
|
end
|
598
625
|
|
@@ -601,7 +628,7 @@ module RDF::RDFXML
|
|
601
628
|
if (CORE_SYNTAX_TERMS + [RDF.Description.to_s] + OLD_TERMS).include?(el.uri.to_s)
|
602
629
|
warn = "Invalid use of rdf:#{el.name}"
|
603
630
|
add_debug(el, warn)
|
604
|
-
raise RDF::ReaderError.new(warn) if
|
631
|
+
raise RDF::ReaderError.new(warn) if validate?
|
605
632
|
end
|
606
633
|
end
|
607
634
|
|
@@ -610,10 +637,19 @@ module RDF::RDFXML
|
|
610
637
|
el.attribute_nodes.each do |attr|
|
611
638
|
if OLD_TERMS.include?(attr.uri.to_s)
|
612
639
|
add_debug(el, "Obsolete attribute '#{attr.uri}'")
|
613
|
-
raise RDF::ReaderError.new("Obsolete attribute '#{attr.uri}'") if
|
640
|
+
raise RDF::ReaderError.new("Obsolete attribute '#{attr.uri}'") if validate?
|
614
641
|
end
|
615
642
|
end
|
616
643
|
end
|
617
644
|
|
645
|
+
def uri(value, append = nil)
|
646
|
+
value = RDF::URI.new(value)
|
647
|
+
value = value.join(append) if append
|
648
|
+
value.validate! if validate?
|
649
|
+
value.canonicalize! if canonicalize?
|
650
|
+
value = RDF::URI.intern(value) if intern?
|
651
|
+
value
|
652
|
+
end
|
653
|
+
|
618
654
|
end
|
619
655
|
end
|