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 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