rdf-rdfxml 0.2.3 → 0.3.0

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 CHANGED
@@ -6,6 +6,8 @@
6
6
  --markup rdoc
7
7
  --readme README.rdoc
8
8
  -
9
+ README.rdoc
10
+ History.rdoc
9
11
  AUTHORS
10
12
  CONTRIBUTORS
11
13
  VERSION
@@ -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.2.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 = <<-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.2.2')
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', '>= 0.2.2')
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.txt AUTHORS CONTRIBUTORS)
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 'spec/rake/spectask'
30
- Spec::Rake::SpecTask.new(:spec) do |spec|
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
- Spec::Rake::SpecTask.new("spec:rcov") do |spec|
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
- Spec::Rake::SpecTask.new("doc:spec") do |spec|
44
- spec.libs << 'lib' << '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.2.3
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 :__default__ or "" to declare default namespace
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 == :__default__ ? "" : prefix.to_s
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, ns_strs, options[:language])
80
- when :libxml then parse_value_libxml(value, ns_strs, options[:language])
81
- when :rexml then parse_value_rexml(value, ns_strs, options[:language])
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, ns_strs, language)
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
@@ -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, suffix = attr_name.to_s.split(":")
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[suffix] = attr_value
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
- @base = RDF::URI.intern(b)
103
- @base.fragment = nil
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] input
117
- # @option options [Array] :debug (nil) Array to place debug messages
118
- # @option options [Boolean] :strict (false) Raise Error if true, continue with lax parsing, otherwise
119
- # @option options [Boolean] :base_uri (nil) Base URI to use for relative URIs.
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 [Reader] reader
123
- # @raise [Error]:: Raises RDF::ReaderError if _strict_
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
- @strict = options[:strict]
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? && @strict
138
- raise RDF::ReaderError, "Empty document" if (@doc.nil? || @doc.root.nil?) && @strict
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 $DEBUG
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 parsing mode is _strict_.
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 _strict_
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 @strict
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.escape(id), nil) if id
338
- resourceAttr = RDF::NTriples.escape(resourceAttr) if resourceAttr
339
- nodeID = nodeID_check(el, RDF::NTriples.escape(nodeID)) if nodeID
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] = RDF::URI.intern(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 @strict
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 @strict
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 @strict
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 @strict
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 @strict
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 @strict
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.escape(id.value)}'")
524
- id_check(el, RDF::NTriples.escape(id.value), ec.base) # Returns URI
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.escape(nodeID.value))
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.escape(about.value)
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
- if NC_REGEXP.match(id)
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 @strict
563
- nil
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 @strict
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 @strict
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 @strict
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 @strict
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 @strict
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