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 +4 -4
- data/README.md +5 -5
- data/VERSION +1 -1
- data/lib/rdf/rdfxml/extensions.rb +54 -0
- data/lib/rdf/rdfxml/reader.rb +2 -3
- data/lib/rdf/rdfxml/writer.rb +402 -187
- data/lib/rdf/rdfxml.rb +2 -1
- metadata +30 -39
- data/lib/rdf/rdfxml/patches/nokogiri_hacks.rb +0 -23
- data/lib/rdf/rdfxml/writer/haml_templates.rb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31d21f8a5ec4aaeb5a8cb7bb31f93fbc593021e5a625cd08449eea5d805b5a27
|
4
|
+
data.tar.gz: 82f02071b30962db802433efa1f2229d981c6f072589b1815318fd4c88b17927
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
[](https://badge.fury.io/rb/rdf-rdfxml)
|
6
6
|
[](https://github.com/ruby-rdf/rdf-rdfxml/actions?query=workflow%3ACI)
|
7
7
|
[](https://coveralls.io/github/ruby-rdf/rdf-rdfxml?branch=develop)
|
8
8
|
[](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 >=
|
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.
|
46
|
-
* [
|
47
|
-
* Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (>= 1.
|
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.
|
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
|
data/lib/rdf/rdfxml/reader.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
begin
|
2
2
|
require 'nokogiri'
|
3
|
-
rescue LoadError
|
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
|
-
|
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?
|
data/lib/rdf/rdfxml/writer.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
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::
|
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
|
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 [
|
97
|
-
#
|
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 [
|
103
|
-
#
|
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 [
|
107
|
-
#
|
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
|
-
|
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
|
-
|
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
|
236
|
+
# Yields each property to be rendered separately.
|
145
237
|
#
|
146
238
|
# @param [Array<RDF::Resource>] subject
|
147
239
|
# Subject to render
|
148
|
-
# @param [
|
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
|
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
|
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
|
249
|
+
# Optional @rel property description, a QName, URI or Node definition.
|
159
250
|
# @option options [String] typeof (nil)
|
160
|
-
# RDF type as a
|
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 <li>, 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
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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
|
-
|
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
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
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
|
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 [
|
242
|
-
#
|
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
|
-
|
247
|
-
|
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
|
-
|
277
|
-
|
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
|
-
|
284
|
-
|
285
|
-
end
|
332
|
+
log_debug {"list: #{list.inspect} #{list.to_a}"}
|
333
|
+
render_collection(property, list, builder, **options)
|
286
334
|
end
|
287
|
-
end
|
335
|
+
end
|
288
336
|
end
|
289
337
|
|
290
|
-
if objects.length
|
291
|
-
|
292
|
-
objects.
|
293
|
-
|
294
|
-
|
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
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
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 [
|
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(
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
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
|
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
|
434
|
+
# For RDF/XML, make sure that all predicates have QNames
|
380
435
|
# @param [Statement] statement
|
381
436
|
def preprocess_statement(statement)
|
382
|
-
|
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
|
-
|
385
|
-
|
386
|
-
|
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
|
-
#
|
390
|
-
|
391
|
-
|
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 {"
|
606
|
+
log_debug {"ensure_qname: generated prefix #{@gen_prefix} for #{base_uri}"}
|
403
607
|
@uri_to_prefix[base_uri] = @gen_prefix
|
404
|
-
@
|
608
|
+
@uri_to_qname[uri] = "#{@gen_prefix}:#{suffix}"
|
405
609
|
prefix(@gen_prefix, base_uri)
|
406
|
-
|
610
|
+
get_qname(resource)
|
407
611
|
end
|
408
612
|
end
|
409
|
-
|
410
|
-
#
|
411
|
-
# @param [
|
412
|
-
# @return [
|
413
|
-
def
|
414
|
-
|
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
|
-
#
|
419
|
-
# @
|
420
|
-
|
421
|
-
|
422
|
-
|
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
|
-
|
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.
|
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-
|
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.
|
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.
|
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.
|
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.
|
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:
|
57
|
+
name: builder
|
72
58
|
requirement: !ruby/object:Gem::Requirement
|
73
59
|
requirements:
|
74
60
|
- - "~>"
|
75
61
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
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: '
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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: '
|
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.
|
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
|