rdf-rdfxml 3.2.1 → 3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfa748c97db5ab4bb41a371438ff9b948da9e283be1ca9236c22011c1063ef4a
4
- data.tar.gz: 9728665fbc8e96663b2f43761d78b997dd0514f77ff58bbeb178fc9a295ccc5e
3
+ metadata.gz: 31d21f8a5ec4aaeb5a8cb7bb31f93fbc593021e5a625cd08449eea5d805b5a27
4
+ data.tar.gz: 82f02071b30962db802433efa1f2229d981c6f072589b1815318fd4c88b17927
5
5
  SHA512:
6
- metadata.gz: ba53a0163d5d8b3fa8c6023afcdec46348336df48f69a6f4a8a388eefeba0450adedd6a3525666afb8e6dcb789e30a9d10fcbda8b09f3df2833c28e27d126ced
7
- data.tar.gz: 736215a450c7efe0ba7c94c8f96c1bfc0cf1412af4019e36e7cb962106f7b47144fb635b65236a23e1e8ebf141c8970ef0200f8684b231406715aeddceab02d0
6
+ metadata.gz: 40396b842bcfc0036f89d2c54240df74214cf0f53d1b0d25533e51a04abad3f3e1d354e1dbe3e5268c1fd45abd548413edadc6dc9dcee83ea219ac896317c495
7
+ data.tar.gz: 8126b7218906cf1d25a76c066af26fa2ad033531299df32095bfa27b8446eab886ea263e477f23d323354b1b5852ae2f4e2057295f30e641459d7d24681218be
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [RDF/XML][] reader/writer for [RDF.rb][].
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/rdf-rdfxml.png)](https://badge.fury.io/rb/rdf-rdfxml)
5
+ [![Gem Version](https://badge.fury.io/rb/rdf-rdfxml.svg)](https://badge.fury.io/rb/rdf-rdfxml)
6
6
  [![Build Status](https://github.com/ruby-rdf/rdf-rdfxml/workflows/CI/badge.svg?branch=develop)](https://github.com/ruby-rdf/rdf-rdfxml/actions?query=workflow%3ACI)
7
7
  [![Coverage Status](https://coveralls.io/repos/ruby-rdf/rdf-rdfxml/badge.svg?branch=develop)](https://coveralls.io/github/ruby-rdf/rdf-rdfxml?branch=develop)
8
8
  [![Gitter chat](https://badges.gitter.im/ruby-rdf/rdf.png)](https://gitter.im/ruby-rdf/rdf)
@@ -20,7 +20,7 @@ Install with `gem install rdf-rdfxml`
20
20
 
21
21
  * 100% free and unencumbered [public domain](https://unlicense.org/) software.
22
22
  * Implements a complete parser for [RDF/XML][].
23
- * Compatible with Ruby >= 2.6.
23
+ * Compatible with Ruby >= 3.0.
24
24
 
25
25
  ## Usage:
26
26
  Instantiate a parser and parse source, specifying type and base-URL
@@ -42,9 +42,9 @@ Write a graph to a file:
42
42
  end
43
43
 
44
44
  ## Dependencies
45
- * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.2)
46
- * [Haml](https://rubygems.org/gems/haml) (~>- 5.2)
47
- * Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (>= 1.12)
45
+ * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.3)
46
+ * [Builder](https://rubygems.org/gems/builder) (~>- 3.2)
47
+ * Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (>= 1.15)
48
48
 
49
49
  ## Documentation
50
50
  Full documentation available on [Rubydoc.info][RDF/XML doc])
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.1
1
+ 3.3.0
@@ -0,0 +1,54 @@
1
+ # Extend builder to allow for better control of whitespace in XML Literals
2
+
3
+ require 'builder'
4
+
5
+ module Builder
6
+ # Extends XmlMarkup#tag! to better control whitespace when adding content from a block
7
+ #
8
+ class RdfXml < Builder::XmlMarkup
9
+ # Create a tag named +sym+. Other than the first argument which
10
+ # is the tag name, the arguments are the same as the tags
11
+ # implemented via <tt>method_missing</tt>.
12
+ #
13
+ # @see https://github.com/jimweirich/builder/blob/master/lib/builder/xmlbase.rb
14
+ def tag!(sym, *args, &block)
15
+ text = nil
16
+ attrs = args.last.is_a?(::Hash) ? args.last : {}
17
+ return super unless block && attrs[:no_whitespace]
18
+ attrs.delete(:no_whitespace)
19
+
20
+ sym = "#{sym}:#{args.shift}".to_sym if args.first.kind_of?(::Symbol)
21
+
22
+ args.each do |arg|
23
+ case arg
24
+ when ::Hash
25
+ attrs.merge!(arg)
26
+ when nil
27
+ attrs.merge!({:nil => true}) if explicit_nil_handling?
28
+ else
29
+ text ||= ''
30
+ text << arg.to_s
31
+ end
32
+ end
33
+
34
+ unless text.nil?
35
+ ::Kernel::raise ::ArgumentError,
36
+ "XmlMarkup cannot mix a text argument with a block"
37
+ end
38
+
39
+ # Indent
40
+ _indent
41
+ #unless @indent == 0 || @level == 0
42
+ # text!(" " * (@level * @indent))
43
+ #end
44
+
45
+ _start_tag(sym, attrs)
46
+ begin
47
+ _nested_structures(block)
48
+ ensure
49
+ _end_tag(sym)
50
+ _newline
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,6 +1,6 @@
1
1
  begin
2
2
  require 'nokogiri'
3
- rescue LoadError => e
3
+ rescue LoadError
4
4
  :rexml
5
5
  end
6
6
  require 'rdf/xsd'
@@ -91,7 +91,7 @@ module RDF::RDFXML
91
91
  # Produce the next list entry for this context
92
92
  def li_next
93
93
  @li_counter += 1
94
- predicate = RDF["_#{@li_counter}"]
94
+ RDF["_#{@li_counter}"]
95
95
  end
96
96
 
97
97
  # Set XML base. Ignore any fragment
@@ -328,7 +328,6 @@ module RDF::RDFXML
328
328
  end
329
329
 
330
330
  # Handle the propertyEltList children events in document order
331
- li_counter = 0 # this will increase for each li we iterate through
332
331
  el.children.each do |child|
333
332
  log_fatal "child must be a proxy not a #{child.class}" unless child.is_a?(@implementation::NodeProxy)
334
333
  next unless child.element?
@@ -1,4 +1,4 @@
1
- require 'rdf/rdfa'
1
+ require_relative 'extensions'
2
2
 
3
3
  module RDF::RDFXML
4
4
  ##
@@ -47,12 +47,22 @@ module RDF::RDFXML
47
47
  # end
48
48
  #
49
49
  # @author [Gregg Kellogg](http://greggkellogg.net/)
50
- class Writer < RDF::RDFa::Writer
50
+ class Writer < RDF::Writer
51
51
  format RDF::RDFXML::Format
52
52
  include RDF::Util::Logger
53
53
 
54
54
  VALID_ATTRIBUTES = [:none, :untyped, :typed]
55
55
 
56
+ # Defines rdf:type of subjects to be emitted at the beginning of the document.
57
+ # @return [Array<URI>]
58
+ attr :top_classes
59
+
60
+ # @return [Graph] Graph of statements serialized
61
+ attr_accessor :graph
62
+
63
+ # @return [RDF::URI] Base URI used for relativizing URIs
64
+ attr_accessor :base_uri
65
+
56
66
  ##
57
67
  # RDF/XML Writer options
58
68
  # @see https://ruby-rdf.github.io/rdf/RDF/Writer#options-class_method
@@ -71,8 +81,8 @@ module RDF::RDFXML
71
81
  RDF::CLI::Option.new(
72
82
  symbol: :lang,
73
83
  datatype: String,
74
- on: ["--lang"],
75
- description: "Output as root @lang attribute, and avoid generation _@lang_ where possible."),
84
+ on: ["--lang LANG", :REQUIRED],
85
+ description: "Output as root xml:lang attribute, and avoid generation xml:lang, where possible.") {|arg| RDF::URI(arg)},
76
86
  RDF::CLI::Option.new(
77
87
  symbol: :max_depth,
78
88
  datatype: Integer,
@@ -93,71 +103,152 @@ module RDF::RDFXML
93
103
  # the output stream
94
104
  # @param [Hash{Symbol => Object}] options
95
105
  # any additional options
96
- # @option options [Boolean] :canonicalize (false)
97
- # whether to canonicalize literals when serializing
98
- # @option options [Hash] :prefixes (Hash.new)
99
- # the prefix mappings to use (not supported by all writers)
106
+ # @option options [Symbol] :attributes (nil)
107
+ # How to use XML attributes when serializing, one of :none, :untyped, :typed. The default is :none.
100
108
  # @option options [#to_s] :base_uri (nil)
101
109
  # the base URI to use when constructing relative URIs
102
- # @option options [Integer] :max_depth (10)
103
- # Maximum depth for recursively defining resources
110
+ # @option options [Boolean] :canonicalize (false)
111
+ # whether to canonicalize literals when serializing
112
+ # @option options [String] :default_namespace (nil)
113
+ # URI to use as default namespace, same as prefix(nil)
104
114
  # @option options [#to_s] :lang (nil)
105
115
  # Output as root xml:lang attribute, and avoid generation _xml:lang_ where possible
106
- # @option options [Symbol] :attributes (nil)
107
- # How to use XML attributes when serializing, one of :none, :untyped, :typed. The default is :none.
116
+ # @option options [Integer] :max_depth (10)
117
+ # Maximum depth for recursively defining resources
118
+ # @option options [Hash] :prefixes (Hash.new)
119
+ # the prefix mappings to use (not supported by all writers)
108
120
  # @option options [Boolean] :standard_prefixes (false)
109
121
  # Add standard prefixes to _prefixes_, if necessary.
110
- # @option options [String] :default_namespace (nil)
111
- # URI to use as default namespace, same as prefix(nil)
112
122
  # @option options [String] :stylesheet (nil)
113
123
  # URI to use as @href for output stylesheet processing instruction.
124
+ # @option options [Array<RDF::URI>] :top_classes ([RDF::RDFS.Class])
125
+ # Defines rdf:type of subjects to be emitted at the beginning of the document.
114
126
  # @yield [writer]
115
127
  # @yieldparam [RDF::Writer] writer
116
128
  def initialize(output = $stdout, **options, &block)
117
- super
118
- end
129
+ super do
130
+ @graph = RDF::Graph.new
131
+ @uri_to_prefix = {}
132
+ @uri_to_qname = {}
133
+ @top_classes = options[:top_classes] || [RDF::RDFS.Class]
119
134
 
120
- # @return [Hash<Symbol => String>]
121
- def haml_template
122
- return @haml_template if @haml_template
123
- case @options[:haml]
124
- when Hash then @options[:haml]
125
- else DEFAULT_HAML
135
+ block.call(self) if block_given?
126
136
  end
127
137
  end
128
138
 
139
+ ##
140
+ # Addes a triple to be serialized
141
+ # @param [RDF::Resource] subject
142
+ # @param [RDF::URI] predicate
143
+ # @param [RDF::Value] object
144
+ # @return [void]
145
+ # @raise [NotImplementedError] unless implemented in subclass
146
+ # @abstract
147
+ # @raise [RDF::WriterError] if validating and attempting to write an invalid {RDF::Term}.
148
+ def write_triple(subject, predicate, object)
149
+ @graph.insert(RDF::Statement(subject, predicate, object))
150
+ end
151
+
129
152
  def write_epilogue
130
- @force_RDF_about = {}
131
153
  @max_depth = @options.fetch(:max_depth, 10)
132
154
  @attributes = @options.fetch(:attributes, :none)
155
+ @base_uri = RDF::URI(@options[:base_uri]) if @options[:base_uri]
156
+ @lang = @options[:lang]
157
+ self.reset
158
+
159
+ log_debug {"\nserialize: graph size: #{@graph.size}"}
160
+
161
+ preprocess
162
+ # Prefixes
163
+ prefix = prefixes.keys.map {|pk| "#{pk}: #{prefixes[pk]}"}.sort.join(" ") unless prefixes.empty?
164
+ log_debug {"\nserialize: prefixes: #{prefix.inspect}"}
165
+
166
+ @subjects = order_subjects
167
+
168
+ # Generate document
169
+ doc = render_document(@subjects,
170
+ lang: @lang,
171
+ base: base_uri,
172
+ prefix: prefix,
173
+ stylesheet: @options[:stylesheet]) do |s|
174
+ subject(s)
175
+ end
176
+ @output.write(doc)
133
177
 
134
178
  super
135
179
  end
136
180
 
137
181
  protected
182
+
183
+ # Reset parser to run again
184
+ def reset
185
+ @options[:log_depth] = 0
186
+ @references = {}
187
+ @serialized = {}
188
+ @subjects = {}
189
+ end
190
+
191
+ # Render document using `haml_template[:doc]`. Yields each subject to be rendered separately.
192
+ #
193
+ # @param [Array<RDF::Resource>] subjects
194
+ # Ordered list of subjects. Template must yield to each subject, which returns
195
+ # the serialization of that subject (@see #subject_template)
196
+ # @param [Hash{Symbol => Object}] options Rendering options passed to Haml render.
197
+ # @option options [RDF::URI] base (nil)
198
+ # Base URI added to document, used for shortening URIs within the document.
199
+ # @option options [Symbol, String] language (nil)
200
+ # Value of @lang attribute in document, also allows included literals to omit
201
+ # an @lang attribute if it is equivalent to that of the document.
202
+ # @option options [String] title (nil)
203
+ # Value of html>head>title element.
204
+ # @option options [String] prefix (nil)
205
+ # Value of @prefix attribute.
206
+ # @option options [String] haml (haml_template[:doc])
207
+ # Haml template to render.
208
+ # @yield [subject]
209
+ # Yields each subject
210
+ # @yieldparam [RDF::URI] subject
211
+ # @yieldparam [Builder::RdfXml] builder
212
+ # @yieldreturn [:ignored]
213
+ # @return String
214
+ # The rendered document is returned as a string
215
+ def render_document(subjects, lang: nil, base: nil, **options, &block)
216
+ builder = Builder::RdfXml.new(indent: 2)
217
+ builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
218
+ builder.instruct! :'xml-stylesheet', type: 'text/xsl', href: options[:stylesheet] if options[:stylesheet]
219
+ attrs = prefix_attrs
220
+ attrs[:"xml:lang"] = lang if lang
221
+ attrs[:"xml:base"] = base if base
222
+
223
+ builder.rdf(:RDF, **attrs) do |b|
224
+ subjects.each do |subject|
225
+ render_subject(subject, b, **options)
226
+ end
227
+ end
228
+ end
229
+
138
230
  # Render a subject using `haml_template[:subject]`.
139
231
  #
140
232
  # The _subject_ template may be called either as a top-level element, or recursively under another element if the _rel_ local is not nil.
141
233
  #
142
234
  # For RDF/XML, removes from predicates those that can be rendered as attributes, and adds the `:attr_props` local for the Haml template, which includes all attributes to be rendered as properties.
143
235
  #
144
- # Yields each predicate/property to be rendered separately (@see #render_property_value and `#render_property_values`).
236
+ # Yields each property to be rendered separately.
145
237
  #
146
238
  # @param [Array<RDF::Resource>] subject
147
239
  # Subject to render
148
- # @param [Array<RDF::Resource>] predicates
149
- # Predicates of subject. Each property is yielded for separate rendering.
240
+ # @param [Builder::RdfXml] builder
150
241
  # @param [Hash{Symbol => Object}] options Rendering options passed to Haml render.
151
242
  # @option options [String] about (nil)
152
- # About description, a CURIE, URI or Node definition.
243
+ # About description, a QName, URI or Node definition.
153
244
  # May be nil if no @about is rendered (e.g. unreferenced Nodes)
154
245
  # @option options [String] resource (nil)
155
- # Resource description, a CURIE, URI or Node definition.
246
+ # Resource description, a QName, URI or Node definition.
156
247
  # May be nil if no @resource is rendered
157
248
  # @option options [String] rel (nil)
158
- # Optional @rel property description, a CURIE, URI or Node definition.
249
+ # Optional @rel property description, a QName, URI or Node definition.
159
250
  # @option options [String] typeof (nil)
160
- # RDF type as a CURIE, URI or Node definition.
251
+ # RDF type as a QName, URI or Node definition.
161
252
  # If :about is nil, this defaults to the empty string ("").
162
253
  # @option options [:li, nil] element (nil)
163
254
  # Render with &lt;li&gt;, otherwise with template default.
@@ -167,102 +258,54 @@ module RDF::RDFXML
167
258
  # Yields each predicate
168
259
  # @yieldparam [RDF::URI] predicate
169
260
  # @yieldreturn [:ignored]
170
- # @return String
171
- # The rendered document is returned as a string
172
- # Return Haml template for document from `haml_template[:subject]`
173
- def render_subject(subject, predicates, **options, &block)
174
- # extract those properties that can be rendered as attributes
175
- attr_props = if [:untyped, :typed].include?(@attributes)
176
- options[:property_values].inject({}) do |memo, (prop, values)|
177
- object = values.first
178
- if values.length == 1 &&
179
- object.literal? &&
180
- (object.plain? || @attributes == :typed) &&
181
- get_lang(object).nil?
261
+ # @return Builder::RdfXml
262
+ def render_subject(subject, builder, **options, &block)
263
+ return nil if is_done?(subject)
264
+
265
+ attr_props, embed_props, types = prop_partition(properties_for_subject(subject))
266
+
267
+ # The first type is used for
268
+ first_type = types.shift
269
+ type_qname = get_qname(first_type) if first_type && !first_type.node?
270
+ type_qname = nil unless type_qname.is_a?(String)
271
+ types.unshift(first_type) if first_type && !type_qname
272
+ type_qname ||= "rdf:Description"
273
+
274
+ attr_props = attr_props.merge("rdf:nodeID": subject.id) if subject.node? && ref_count(subject) >= 1
275
+ attr_props = attr_props.merge("rdf:about": subject.relativize(base_uri)) if subject.uri?
276
+
277
+ log_debug {"render_subject(#{subject.inspect})"}
278
+ subject_done(subject)
182
279
 
183
- memo[get_qname(RDF::URI(prop))] = object.value
280
+ builder.tag!(type_qname, **attr_props) do |b|
281
+ types.each do |type|
282
+ if type.node?
283
+ b.tag!("rdf:type", "rdf:nodeID": type.id)
284
+ else
285
+ b.tag!("rdf:type", "rdf:resource": type.to_s)
184
286
  end
185
- memo
186
287
  end
187
- else
188
- {}
189
- end
190
-
191
- predicates -= attr_props.keys.map {|k| expand_curie(k).to_s}
192
- super(subject, predicates, **options.merge(attr_props: attr_props), &block)
193
- end
194
- # See if we can serialize as attribute.
195
- # * untyped attributes that aren't duplicated where xml:lang == @lang
196
- # * typed attributes that aren't duplicated if @dt_as_attr is true
197
- # * rdf:type
198
- def predicate_as_attribute?(prop, object)
199
- [:untyped, :typed].include?(@attributes) && (
200
- prop == RDF.type ||
201
- [:typed].include?(@attributes) && object.literal? && object.typed? ||
202
- (object.literal? && object.simple? || @lang && object.language.to_s == @lang.to_s)
203
- )
204
- end
205
288
 
206
- # Render document using `haml_template[:doc]`. Yields each subject to be rendered separately.
207
- #
208
- # For RDF/XML pass along a stylesheet option.
209
- #
210
- # @param [Array<RDF::Resource>] subjects
211
- # Ordered list of subjects. Template must yield to each subject, which returns
212
- # the serialization of that subject (@see #subject_template)
213
- # @param [Hash{Symbol => Object}] options Rendering options passed to Haml render.
214
- # @option options [RDF::URI] base (nil)
215
- # Base URI added to document, used for shortening URIs within the document.
216
- # @option options [Symbol, String] language (nil)
217
- # Value of @lang attribute in document, also allows included literals to omit
218
- # an @lang attribute if it is equivalent to that of the document.
219
- # @option options [String] title (nil)
220
- # Value of html>head>title element.
221
- # @option options [String] prefix (nil)
222
- # Value of @prefix attribute.
223
- # @option options [String] haml (haml_template[:doc])
224
- # Haml template to render.
225
- # @yield [subject]
226
- # Yields each subject
227
- # @yieldparam [RDF::URI] subject
228
- # @yieldreturn [:ignored]
229
- # @return String
230
- # The rendered document is returned as a string
231
- def render_document(subjects, **options, &block)
232
- super(subjects, **options.merge(stylesheet: @options[:stylesheet]), &block)
289
+ log_depth do
290
+ embed_props.each do |p, objects|
291
+ render_property(p, objects, b, **options)
292
+ end
293
+ end
294
+ end
233
295
  end
234
296
 
235
- # Render a single- or multi-valued predicate using `haml_template[:property_value]` or `haml_template[:property_values]`. Yields each object for optional rendering. The block should only render for recursive subject definitions (i.e., where the object is also a subject and is rendered underneath the first referencing subject).
236
- #
237
- # For RDF/XML, pass the `:no_list_literals` option onto the `RDFa` implementation because of special considerations for lists in RDF/XML.
297
+ # Render a single- or multi-valued property. Yields each object for optional rendering. The block should only render for recursive subject definitions (i.e., where the object is also a subject and is rendered underneath the first referencing subject).
238
298
  #
239
299
  # If a multi-valued property definition is not found within the template, the writer will use the single-valued property definition multiple times.
240
300
  #
241
- # @param [Array<RDF::Resource>] predicate
242
- # Predicate to render.
301
+ # @param [String] property
302
+ # Property to render, already in QName form.
243
303
  # @param [Array<RDF::Resource>] objects
244
304
  # List of objects to render. If the list contains only a single element, the :property_value template will be used. Otherwise, the :property_values template is used.
305
+ # @param [Builder::RdfXml] builder
245
306
  # @param [Hash{Symbol => Object}] options Rendering options passed to Haml render.
246
- # @option options [String] :haml (haml_template[:property_value], haml_template[:property_values])
247
- # Haml template to render. Otherwise, uses `haml_template[:property_value] or haml_template[:property_values]`
248
- # depending on the cardinality of objects.
249
- # @option options [Boolean] :no_list_literals
250
- # Do not serialize as a list if any elements are literal.
251
- # @yield object, inlist
252
- # Yields object and if it is contained in a list.
253
- # @yieldparam [RDF::Resource] object
254
- # @yieldparam [Boolean] inlist
255
- # @yieldreturn [String, nil]
256
- # The block should only return a string for recursive object definitions.
257
- # @return String
258
- # The rendered document is returned as a string
259
- def render_property(predicate, objects, **options, &block)
260
- log_debug {"render_property(#{predicate}): #{objects.inspect}, #{options.inspect}"}
261
- # If there are multiple objects, and no :property_values is defined, call recursively with
262
- # each object
263
-
264
- template = options[:haml]
265
- template ||= haml_template[:property_value]
307
+ def render_property(property, objects, builder, **options)
308
+ log_debug {"render_property(#{property}): #{objects.inspect}"}
266
309
 
267
310
  # Separate out the objects which are lists and render separately
268
311
  lists = objects.
@@ -270,38 +313,57 @@ module RDF::RDFXML
270
313
  map {|o| RDF::List.new(subject: o, graph: @graph)}.
271
314
  select {|l| l.valid? && l.none?(&:literal?)}
272
315
 
316
+ objects = objects - lists.map(&:subject)
317
+
273
318
  unless lists.empty?
274
319
  # Render non-list objects
275
- log_debug {"properties with lists: #{lists} non-lists: #{objects - lists.map(&:subject)}"}
276
- nl = log_depth {render_property(predicate, objects - lists.map(&:subject), options, &block)} unless objects == lists.map(&:subject)
277
- return nl.to_s + lists.map do |list|
320
+ log_debug(depth: log_depth + 1) {"properties with lists: #{lists} non-lists: #{objects - lists.map(&:subject)}"}
321
+
322
+ unless objects.empty?
323
+ render_property(property, objects, builder, **options)
324
+ end
325
+
326
+ # Render each list
327
+ lists.each do |list|
278
328
  # Render each list as multiple properties and set :inlist to true
279
329
  list.each_statement {|st| subject_done(st.subject)}
280
330
 
281
- log_debug {"list: #{list.inspect} #{list.to_a}"}
282
331
  log_depth do
283
- render_collection(predicate, list, **options) do |object|
284
- yield(object, true) if block_given?
285
- end
332
+ log_debug {"list: #{list.inspect} #{list.to_a}"}
333
+ render_collection(property, list, builder, **options)
286
334
  end
287
- end.join(" ")
335
+ end
288
336
  end
289
337
 
290
- if objects.length > 1
291
- # Render each property using property_value template
292
- objects.map do |object|
293
- log_depth {render_property(predicate, [object], **options, &block)}
294
- end.join(" ")
338
+ if objects.length == 1
339
+ recurse = log_depth <= @max_depth
340
+ object = objects.first
341
+
342
+ if recurse && !is_done?(object)
343
+ builder.tag!(property) do |b|
344
+ render_subject(object, b, **options)
345
+ end
346
+ elsif object.literal? && object.datatype == RDF.XMLLiteral
347
+ builder.tag!(property, "rdf:parseType": "Literal", no_whitespace: true) do |b|
348
+ b << object.value
349
+ end
350
+ elsif object.literal?
351
+ attrs = {}
352
+ attrs[:"xml:lang"] = object.language if object.language?
353
+ attrs[:"rdf:datatype"] = object.datatype if object.datatype?
354
+ builder.tag!(property, object.value.to_s, **attrs)
355
+ elsif object.node?
356
+ builder.tag!(property, "rdf:nodeID": object.id)
357
+ else
358
+ builder.tag!(property, "rdf:resource": object.relativize(base_uri))
359
+ end
295
360
  else
296
- log_fatal("Missing property template", exception: RDF::WriterError) if template.nil?
297
-
298
- options = {
299
- object: objects.first,
300
- predicate: predicate,
301
- property: get_qname(predicate),
302
- recurse: log_depth <= @max_depth
303
- }.merge(options)
304
- hamlify(template, **options, &block)
361
+ # Render each property using property_value template
362
+ objects.each do |object|
363
+ log_depth do
364
+ render_property(property, [object], builder, **options)
365
+ end
366
+ end
305
367
  end
306
368
  end
307
369
 
@@ -309,27 +371,27 @@ module RDF::RDFXML
309
371
  # Render a collection, which may be included in a property declaration, or
310
372
  # may be recursive within another collection
311
373
  #
312
- # @param [RDF::URI] predicate
374
+ # @param [String] property in QName form
313
375
  # @param [RDF::List] list
376
+ # @param [Builder::RdfXml] builder
314
377
  # @param [Hash{Symbol => Object}] options
315
- # @yield object
316
- # Yields object, unless it is an included list
317
- # @yieldparam [RDF::Resource] object
318
- # @yieldreturn [String, nil]
319
- # The block should only return a string for recursive object definitions.
320
378
  # @return String
321
379
  # The rendered collection is returned as a string
322
- def render_collection(predicate, list, **options, &block)
323
- template = options[:haml] || haml_template[:collection]
324
-
325
- options = {
326
- list: list,
327
- predicate: predicate,
328
- property: get_qname(predicate),
329
- recurse: log_depth <= @max_depth,
330
- }.merge(options)
331
- hamlify(template, **options) do |object|
332
- yield object
380
+ def render_collection(property, list, builder, **options, &block)
381
+ builder.tag!(property, "rdf:parseType": "Collection") do |b|
382
+ list.each do |object|
383
+ if log_depth <= @max_depth && !is_done?(object)
384
+ render_subject(object, b)
385
+ elsif object.node?
386
+ if ref_count(object) > 1
387
+ b.tag!("rdf:Description", "rdf:nodeID": object.id)
388
+ else
389
+ b.tag!("rdf:Description")
390
+ end
391
+ else
392
+ b.tag!("rdf:Description", "rdf:about": object.relativize(base_uri))
393
+ end
394
+ end
333
395
  end
334
396
  end
335
397
 
@@ -337,7 +399,7 @@ module RDF::RDFXML
337
399
  # @return [Hash{String => String}]
338
400
  def prefix_attrs
339
401
  prefixes.inject({}) do |memo, (k, v)|
340
- memo[k ? "xmlns:#{k}" : "xmlns"] = v.to_s
402
+ memo[(k ? "xmlns:#{k}" : "xmlns").to_sym] = v.to_s
341
403
  memo
342
404
  end
343
405
  end
@@ -363,32 +425,174 @@ module RDF::RDFXML
363
425
  prefix(nil, @options[:default_namespace])
364
426
  end
365
427
 
366
- # Process each statement to establish CURIEs and Terms
428
+ # Process each statement to establish QNames and Terms
367
429
  @graph.each {|statement| preprocess_statement(statement)}
368
430
  end
369
431
 
370
- ##
371
- # Turn CURIE into a QNAME
372
- def get_qname(uri)
373
- curie = get_curie(uri)
374
- curie.start_with?(":") ? curie[1..-1] : curie
375
- end
376
-
377
432
  # Perform any statement preprocessing required. This is used to perform reference counts and determine required prefixes.
378
433
  #
379
- # For RDF/XML, make sure that all predicates have CURIEs
434
+ # For RDF/XML, make sure that all predicates have QNames
380
435
  # @param [Statement] statement
381
436
  def preprocess_statement(statement)
382
- super
437
+ #log_debug {"preprocess: #{statement.inspect}"}
438
+ bump_reference(statement.object)
439
+ @subjects[statement.subject] = true
440
+ get_qname(statement.subject)
441
+ ensure_qname(statement.predicate)
442
+ statement.predicate == RDF.type && statement.object.uri? ? ensure_qname(statement.object) : get_qname(statement.object)
443
+ get_qname(statement.object.datatype) if statement.object.literal? && statement.object.datatype?
444
+ end
445
+
446
+ private
383
447
 
384
- # Invent a prefix for the predicate, if necessary
385
- ensure_curie(statement.predicate)
386
- ensure_curie(statement.object) if statement.predicate == RDF.type
448
+ # Order subjects for output. Override this to output subjects in another order.
449
+ #
450
+ # Uses #top_classes and #base_uri.
451
+ # @return [Array<Resource>] Ordered list of subjects
452
+ def order_subjects
453
+ seen = {}
454
+ subjects = []
455
+
456
+ # Start with base_uri
457
+ if base_uri && @subjects.keys.include?(base_uri)
458
+ subjects << base_uri
459
+ seen[base_uri] = true
460
+ end
461
+
462
+ # Add distinguished classes
463
+ top_classes.
464
+ select {|s| !seen.include?(s)}.
465
+ each do |class_uri|
466
+ graph.query({predicate: "rdf:type", object: class_uri}).map {|st| st.subject}.sort.uniq.each do |subject|
467
+ #log_debug {"order_subjects: #{subject.inspect}"}
468
+ subjects << subject
469
+ seen[subject] = true
470
+ end
471
+ end
472
+
473
+ # Sort subjects by resources over nodes, ref_counts and the subject URI itself
474
+ recursable = @subjects.keys.
475
+ select {|s| !seen.include?(s)}.
476
+ map {|r| [r.is_a?(RDF::Node) ? 1 : 0, ref_count(r), r]}.
477
+ sort
478
+
479
+ log_debug {"order_subjects: #{recursable.inspect}"}
480
+
481
+ subjects += recursable.map{|r| r.last}
482
+ end
483
+
484
+ # @param [RDF::Resource] subject
485
+ # @return [Hash{String => Object}]
486
+ def properties_for_subject(subject)
487
+ properties = {}
488
+ @graph.query({subject: subject}) do |st|
489
+ key = get_qname(st.predicate.to_s)
490
+ properties[key] ||= []
491
+ properties[key] << st.object
492
+ end
493
+ properties
494
+ end
495
+
496
+ # Partition properties into attributed, embedded, and types
497
+ #
498
+ # @param [Hash{String => Array<RDF::Resource}] properties
499
+ # @return [Hash, Hash, Array<RDF::Resource>]
500
+ def prop_partition(properties)
501
+ attr_props, embed_props = {}, {}
502
+
503
+ type_prop = "rdf:type"
504
+ types = properties.delete(type_prop)
505
+
506
+ # extract those properties that can be rendered as attributes
507
+ if [:untyped, :typed].include?(@attributes)
508
+ properties.each do |prop, values|
509
+ object = values.first
510
+ if values.length == 1 &&
511
+ object.literal? &&
512
+ (object.plain? || @attributes == :typed) &&
513
+ get_lang(object).nil?
514
+
515
+ attr_props[prop.to_sym] = values.first.to_s
516
+ else
517
+ embed_props[prop] = values
518
+ end
519
+ end
520
+ else
521
+ embed_props = properties
522
+ end
523
+
524
+ [attr_props, embed_props, Array(types)]
525
+ end
526
+
527
+ # Return language for literal, if there is no language, or it is the same as the document, return nil
528
+ #
529
+ # @param [RDF::Literal] literal
530
+ # @return [Symbol, nil]
531
+ # @raise [RDF::WriterError]
532
+ def get_lang(literal)
533
+ if literal.is_a?(RDF::Literal)
534
+ literal.language if literal.literal? && literal.language && literal.language.to_s != @lang.to_s
535
+ else
536
+ log_error("Getting language for #{literal.inspect}, which must be a literal")
537
+ nil
538
+ end
387
539
  end
388
540
 
389
- # Make sure a CURIE is defined
390
- def ensure_curie(resource)
391
- if get_curie(resource) == resource.to_s || get_curie(resource).split(':', 2).last =~ /[\.#]/
541
+ # Return appropriate, term, QName or URI for the given resource.
542
+ #
543
+ # @param [RDF::Value, String] resource
544
+ # @return [String] value to use to identify URI
545
+ # @raise [RDF::WriterError]
546
+ def get_qname(resource)
547
+ return @uri_to_qname[resource] if resource.is_a?(String) && @uri_to_qname.key?(resource)
548
+
549
+ case resource
550
+ when RDF::URI
551
+ begin
552
+ uri = resource.to_s
553
+
554
+ qname = case
555
+ when @uri_to_qname.key?(uri)
556
+ @uri_to_qname[uri]
557
+ when base_uri && uri.index(base_uri.to_s) == 0
558
+ #log_debug {"get_qname(#{uri}): base_uri (#{uri.sub(base_uri.to_s, "")})"}
559
+ uri.sub(base_uri.to_s, "")
560
+ when u = @uri_to_prefix.keys.detect {|u| uri.index(u.to_s) == 0}
561
+ #log_debug {"get_qname(#{uri}): uri_to_prefix"}
562
+ # Use a defined prefix
563
+ prefix = @uri_to_prefix[u]
564
+ prefix(prefix, u) # Define for output
565
+ uri.sub(u.to_s, "#{prefix}:")
566
+ when @options[:standard_prefixes] && vocab = RDF::Vocabulary.detect {|v| uri.index(v.to_uri.to_s) == 0}
567
+ #log_debug {"get_qname(#{uri}): standard_prefixes"}
568
+ prefix = vocab.__name__.to_s.split('::').last.downcase
569
+ prefix(prefix, vocab.to_uri) # Define for output
570
+ uri.sub(vocab.to_uri.to_s, "#{prefix}:")
571
+ end
572
+
573
+ # Don't define ill-formed qnames
574
+ @uri_to_qname[uri] = if qname.nil? || qname == ':'
575
+ resource
576
+ elsif qname.start_with?(':')
577
+ qname[1..-1]
578
+ else
579
+ qname
580
+ end
581
+ rescue ArgumentError => e
582
+ log_error("Invalid URI #{uri.inspect}: #{e.message}")
583
+ nil
584
+ end
585
+ when RDF::Node then resource.to_s
586
+ when RDF::Literal then nil
587
+ else
588
+ log_error("Getting QName for #{resource.inspect}, which must be a resource")
589
+ nil
590
+ end
591
+ end
592
+
593
+ # Make sure a QName is defined
594
+ def ensure_qname(resource)
595
+ if get_qname(resource) == resource.to_s || get_qname(resource).split(':', 2).last =~ /[\.#]/
392
596
  uri = resource.to_s
393
597
  # No vocabulary found, invent one
394
598
  # Add bindings for predicates not already having bindings
@@ -399,29 +603,40 @@ module RDF::RDFXML
399
603
  base_uri = uri.to_s[0..separation]
400
604
  suffix = uri.to_s[separation+1..-1]
401
605
  @gen_prefix = @gen_prefix ? @gen_prefix.succ : "ns0"
402
- log_debug {"ensure_curie: generated prefix #{@gen_prefix} for #{base_uri}"}
606
+ log_debug {"ensure_qname: generated prefix #{@gen_prefix} for #{base_uri}"}
403
607
  @uri_to_prefix[base_uri] = @gen_prefix
404
- @uri_to_term_or_curie[uri] = "#{@gen_prefix}:#{suffix}"
608
+ @uri_to_qname[uri] = "#{@gen_prefix}:#{suffix}"
405
609
  prefix(@gen_prefix, base_uri)
406
- get_curie(resource)
610
+ get_qname(resource)
407
611
  end
408
612
  end
409
-
410
- # If base_uri is defined, use it to try to make uri relative
411
- # @param [#to_s] uri
412
- # @return [String]
413
- def relativize(uri)
414
- uri = expand_curie(uri.to_s)
415
- base_uri ? uri.sub(base_uri.to_s, "") : uri
613
+
614
+ # Mark a subject as done.
615
+ # @param [RDF::Resource] subject
616
+ # @return [Boolean]
617
+ def subject_done(subject)
618
+ @serialized[subject] = true
416
619
  end
417
620
 
418
- # Undo CURIE
419
- # @return [RDF::URI]
420
- def expand_curie(curie)
421
- pfx, suffix = curie.split(":", 2)
422
- prefix(pfx) ? prefix(pfx) + suffix : curie
621
+ # Determine if the subject has been completed
622
+ # @param [RDF::Resource] subject
623
+ # @return [Boolean]
624
+ def is_done?(subject)
625
+ @serialized.include?(subject) || !@subjects.include?(subject)
626
+ end
627
+
628
+ # Increase the reference count of this resource
629
+ # @param [RDF::Resource] resource
630
+ # @return [Integer] resulting reference count
631
+ def bump_reference(resource)
632
+ @references[resource] = ref_count(resource) + 1
633
+ end
634
+
635
+ # Return the number of times this node has been referenced in the object position
636
+ # @param [RDF::Node] node
637
+ # @return [Boolean]
638
+ def ref_count(node)
639
+ @references.fetch(node, 0)
423
640
  end
424
641
  end
425
642
  end
426
-
427
- require 'rdf/rdfxml/writer/haml_templates'
data/lib/rdf/rdfxml.rb CHANGED
@@ -2,7 +2,8 @@ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..')))
2
2
  require 'rdf'
3
3
 
4
4
  module RDF
5
- autoload :XML, 'rdf/rdfa/vocab'
5
+ XML = Class.new(Vocabulary("http://www.w3.org/XML/1998/namespace"))
6
+
6
7
  ##
7
8
  # **`RDF::RDFXML`** is an RDF/XML extension for RDF.rb.
8
9
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdf-rdfxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-04-05 00:00:00.000000000 Z
12
+ date: 2023-09-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rdf
@@ -17,42 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '3.2'
20
+ version: '3.3'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '3.2'
27
+ version: '3.3'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rdf-xsd
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '3.2'
34
+ version: '3.3'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '3.2'
42
- - !ruby/object:Gem::Dependency
43
- name: rdf-rdfa
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: '3.2'
49
- type: :runtime
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: '3.2'
41
+ version: '3.3'
56
42
  - !ruby/object:Gem::Dependency
57
43
  name: htmlentities
58
44
  requirement: !ruby/object:Gem::Requirement
@@ -68,47 +54,53 @@ dependencies:
68
54
  - !ruby/object:Gem::Version
69
55
  version: '4.3'
70
56
  - !ruby/object:Gem::Dependency
71
- name: haml
57
+ name: builder
72
58
  requirement: !ruby/object:Gem::Requirement
73
59
  requirements:
74
60
  - - "~>"
75
61
  - !ruby/object:Gem::Version
76
- version: '5.2'
62
+ version: '3.2'
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: 3.2.4
77
66
  type: :runtime
78
67
  prerelease: false
79
68
  version_requirements: !ruby/object:Gem::Requirement
80
69
  requirements:
81
70
  - - "~>"
82
71
  - !ruby/object:Gem::Version
83
- version: '5.2'
72
+ version: '3.2'
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.2.4
84
76
  - !ruby/object:Gem::Dependency
85
77
  name: json-ld
86
78
  requirement: !ruby/object:Gem::Requirement
87
79
  requirements:
88
80
  - - ">="
89
81
  - !ruby/object:Gem::Version
90
- version: '3.2'
82
+ version: '3.3'
91
83
  type: :development
92
84
  prerelease: false
93
85
  version_requirements: !ruby/object:Gem::Requirement
94
86
  requirements:
95
87
  - - ">="
96
88
  - !ruby/object:Gem::Version
97
- version: '3.2'
89
+ version: '3.3'
98
90
  - !ruby/object:Gem::Dependency
99
91
  name: rspec
100
92
  requirement: !ruby/object:Gem::Requirement
101
93
  requirements:
102
94
  - - "~>"
103
95
  - !ruby/object:Gem::Version
104
- version: '3.10'
96
+ version: '3.12'
105
97
  type: :development
106
98
  prerelease: false
107
99
  version_requirements: !ruby/object:Gem::Requirement
108
100
  requirements:
109
101
  - - "~>"
110
102
  - !ruby/object:Gem::Version
111
- version: '3.10'
103
+ version: '3.12'
112
104
  - !ruby/object:Gem::Dependency
113
105
  name: rspec-its
114
106
  requirement: !ruby/object:Gem::Requirement
@@ -129,56 +121,56 @@ dependencies:
129
121
  requirements:
130
122
  - - "~>"
131
123
  - !ruby/object:Gem::Version
132
- version: '3.2'
124
+ version: '3.3'
133
125
  type: :development
134
126
  prerelease: false
135
127
  version_requirements: !ruby/object:Gem::Requirement
136
128
  requirements:
137
129
  - - "~>"
138
130
  - !ruby/object:Gem::Version
139
- version: '3.2'
131
+ version: '3.3'
140
132
  - !ruby/object:Gem::Dependency
141
133
  name: rdf-turtle
142
134
  requirement: !ruby/object:Gem::Requirement
143
135
  requirements:
144
136
  - - "~>"
145
137
  - !ruby/object:Gem::Version
146
- version: '3.2'
138
+ version: '3.3'
147
139
  type: :development
148
140
  prerelease: false
149
141
  version_requirements: !ruby/object:Gem::Requirement
150
142
  requirements:
151
143
  - - "~>"
152
144
  - !ruby/object:Gem::Version
153
- version: '3.2'
145
+ version: '3.3'
154
146
  - !ruby/object:Gem::Dependency
155
147
  name: rdf-spec
156
148
  requirement: !ruby/object:Gem::Requirement
157
149
  requirements:
158
150
  - - "~>"
159
151
  - !ruby/object:Gem::Version
160
- version: '3.2'
152
+ version: '3.3'
161
153
  type: :development
162
154
  prerelease: false
163
155
  version_requirements: !ruby/object:Gem::Requirement
164
156
  requirements:
165
157
  - - "~>"
166
158
  - !ruby/object:Gem::Version
167
- version: '3.2'
159
+ version: '3.3'
168
160
  - !ruby/object:Gem::Dependency
169
161
  name: rdf-vocab
170
162
  requirement: !ruby/object:Gem::Requirement
171
163
  requirements:
172
164
  - - "~>"
173
165
  - !ruby/object:Gem::Version
174
- version: '3.2'
166
+ version: '3.3'
175
167
  type: :development
176
168
  prerelease: false
177
169
  version_requirements: !ruby/object:Gem::Requirement
178
170
  requirements:
179
171
  - - "~>"
180
172
  - !ruby/object:Gem::Version
181
- version: '3.2'
173
+ version: '3.3'
182
174
  - !ruby/object:Gem::Dependency
183
175
  name: yard
184
176
  requirement: !ruby/object:Gem::Requirement
@@ -206,14 +198,13 @@ files:
206
198
  - UNLICENSE
207
199
  - VERSION
208
200
  - lib/rdf/rdfxml.rb
201
+ - lib/rdf/rdfxml/extensions.rb
209
202
  - lib/rdf/rdfxml/format.rb
210
- - lib/rdf/rdfxml/patches/nokogiri_hacks.rb
211
203
  - lib/rdf/rdfxml/reader.rb
212
204
  - lib/rdf/rdfxml/reader/nokogiri.rb
213
205
  - lib/rdf/rdfxml/reader/rexml.rb
214
206
  - lib/rdf/rdfxml/version.rb
215
207
  - lib/rdf/rdfxml/writer.rb
216
- - lib/rdf/rdfxml/writer/haml_templates.rb
217
208
  homepage: https://github.com/ruby-rdf/rdf-rdfxml
218
209
  licenses:
219
210
  - Unlicense
@@ -231,14 +222,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
231
222
  requirements:
232
223
  - - ">="
233
224
  - !ruby/object:Gem::Version
234
- version: '2.6'
225
+ version: '3.0'
235
226
  required_rubygems_version: !ruby/object:Gem::Requirement
236
227
  requirements:
237
228
  - - ">="
238
229
  - !ruby/object:Gem::Version
239
230
  version: '0'
240
231
  requirements: []
241
- rubygems_version: 3.4.6
232
+ rubygems_version: 3.2.33
242
233
  signing_key:
243
234
  specification_version: 4
244
235
  summary: RDF/XML reader/writer for RDF.rb.
@@ -1,23 +0,0 @@
1
- require 'nokogiri'
2
- class Nokogiri::XML::Node
3
- # URI of namespace + node_name
4
- def uri
5
- ns = self.namespace ? self.namespace.href : RDF::XML.to_s
6
- RDF::URI.intern(ns + self.node_name)
7
- end
8
-
9
- alias_method :attribute_with_ns_without_ffi_null, :attribute_with_ns
10
- ##
11
- # Monkey patch attribute_with_ns, to insure nil is returned for #null?
12
- #
13
- # Get the attribute node with name and namespace
14
- #
15
- # @param [String] name
16
- # @param [String] namespace
17
- # @return [Nokogiri::XML::Attr]
18
- def attribute_with_ns(name, namespace)
19
- a = attribute_with_ns_without_ffi_null(name, namespace)
20
-
21
- (a.respond_to?(:null?) && a.null?) ? nil : a # to ensure FFI Pointer compatibility
22
- end
23
- end
@@ -1,86 +0,0 @@
1
- # Default HAML templates used for generating RDF/XML output from the writer
2
- module RDF::RDFXML
3
- class Writer
4
- # The default set of HAML templates used for RDFa code generation
5
- BASE_HAML = {
6
- identifier: "base",
7
- # Document
8
- # Locals: lang, title, prefix, base, subjects
9
- # Yield: subjects.each
10
- doc: %q(
11
- = %(<?xml version='1.0' encoding='utf-8' ?>)
12
- - if stylesheet
13
- = %(<?xml-stylesheet type="text/xsl" href="#{stylesheet}"?>)
14
- %rdf:RDF{prefix_attrs.merge("xml:lang" => lang, "xml:base" => base)}
15
- - subjects.each do |subject|
16
- != yield(subject)
17
- ),
18
-
19
- # Output for non-leaf resources
20
- # Note that @about may be omitted for Nodes that are not referenced
21
- #
22
- # If _rel_ and _resource_ are not nil, the tag will be written relative
23
- # to a previous subject. If _element_ is :li, the tag will be written
24
- # with <li> instead of <div>.
25
- #
26
- # Locals: subject, typeof, predicates, rel, element, inlist, attr_props
27
- # Yield: predicates.each
28
- subject: %q(
29
- - first_type, *types = typeof.to_s.split(' ')
30
- - (types.unshift(first_type); first_type = nil) if first_type && (first_type.include?('/') || first_type.start_with?('_:'))
31
- - first_type ||= get_qname(RDF.Description)
32
- - first_type = first_type[1..-1] if first_type.to_s.start_with?(":")
33
- - attr_props = attr_props.merge(get_qname(RDF.nodeID) => subject.id) if subject.node? && ref_count(subject) >= 1
34
- - attr_props = attr_props.merge(get_qname(RDF.about) => relativize(subject)) if subject.uri?
35
- - haml_tag(first_type, attr_props) do
36
- - types.each do |type|
37
- - expanded_type = expand_curie(type)
38
- - if expanded_type.start_with?('_:')
39
- - haml_tag(get_qname(RDF.type), "rdf:nodeID" => expanded_type[2..-1])
40
- -else
41
- - haml_tag(get_qname(RDF.type), "rdf:resource" => expanded_type)
42
- - predicates.each do |p|
43
- = yield(p)
44
- ),
45
-
46
- # Output for single-valued properties
47
- # Locals: predicate, object, inlist
48
- # Yields: object
49
- # If nil is returned, render as a leaf
50
- # Otherwise, render result
51
- property_value: %q(
52
- - if recurse && res = yield(object)
53
- - haml_tag(property) do
54
- = res
55
- - elsif object.literal? && object.datatype == RDF.XMLLiteral
56
- - haml_tag(property, :"<", "rdf:parseType" => "Literal") do
57
- = object.value
58
- - elsif object.literal?
59
- - haml_tag(property, :"<", "xml:lang" => object.language, "rdf:datatype" => (object.datatype unless object.plain?)) do
60
- = object.value.to_s.encode(xml: :text)
61
- - elsif object.node?
62
- - haml_tag(property, :"/", "rdf:nodeID" => object.id)
63
- - else
64
- - haml_tag(property, :"/", "rdf:resource" => relativize(object))
65
- ),
66
-
67
- # Outpust for a list
68
- # Locals: predicate, list
69
- # Yields: object
70
- # If nil is returned, render as a leaf
71
- # Otherwise, render result
72
- collection: %q(
73
- - haml_tag(property, get_qname(RDF.parseType) => "Collection") do
74
- - list.each do |object|
75
- - if recurse && res = yield(object)
76
- = res
77
- - elsif object.node?
78
- - haml_tag(get_qname(RDF.Description), :"/", "rdf:nodeID" => (object.id if ref_count(object) > 1))
79
- - else
80
- - haml_tag(get_qname(RDF.Description), :"/", "rdf:about" => relativize(object))
81
- ),
82
- }
83
- HAML_TEMPLATES = {base: BASE_HAML}
84
- DEFAULT_HAML = BASE_HAML
85
- end
86
- end