rdf-rdfxml 3.2.0 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -3
- data/VERSION +1 -1
- data/lib/rdf/rdfxml/extensions.rb +54 -0
- data/lib/rdf/rdfxml/format.rb +3 -1
- data/lib/rdf/rdfxml/reader/nokogiri.rb +1 -1
- data/lib/rdf/rdfxml/reader.rb +2 -3
- data/lib/rdf/rdfxml/writer.rb +403 -188
- data/lib/rdf/rdfxml.rb +2 -1
- metadata +16 -12
- 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: 1e99dd30e3fe9c3457ef54ed1bb66f455e16082e7c0ad72fc30414c0e38a7fad
|
4
|
+
data.tar.gz: ce09170384f2015247954df866fad90a12a305683a5161d10c9c8764b48b9653
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbda846c7dbfd709d03af8164b4d8a89c2f38f464e5867faa6b517bb7392794749e1a692c7f609055fd4af95d8378f65ae3416ee31de7f78e934bd066bccdb21
|
7
|
+
data.tar.gz: 9a3e918e57823b6cf8c16ade45c8d0a47e914448f7efcb94a347e3d6f555ff9ba80ace97cba53f52d229e25f2bf0e3ed6465628d3dc93208401ed495f12a89df
|
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.
|
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)
|
@@ -43,7 +43,8 @@ Write a graph to a file:
|
|
43
43
|
|
44
44
|
## Dependencies
|
45
45
|
* [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.2)
|
46
|
-
*
|
46
|
+
* [Builder](https://rubygems.org/gems/builder) (~>- 3.2)
|
47
|
+
* Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (>= 1.13)
|
47
48
|
|
48
49
|
## Documentation
|
49
50
|
Full documentation available on [Rubydoc.info][RDF/XML doc])
|
@@ -103,5 +104,5 @@ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
|
103
104
|
[YARD]: https://yardoc.org/
|
104
105
|
[YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
105
106
|
[PDD]: https://unlicense.org/#unlicensing-contributions
|
106
|
-
[RDF/XML doc]: https://
|
107
|
+
[RDF/XML doc]: https://ruby-rdf.github.io/rdf-rdfxml/master/frames
|
107
108
|
[RDF-star]: https://w3c.github.io/rdf-star/rdf-star-cg-spec.html
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.
|
1
|
+
3.2.2
|
@@ -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/format.rb
CHANGED
@@ -20,7 +20,9 @@ module RDF::RDFXML
|
|
20
20
|
#
|
21
21
|
# @see http://www.w3.org/TR/rdf-testcases/#ntriples
|
22
22
|
class Format < RDF::Format
|
23
|
-
content_type 'application/rdf+xml',
|
23
|
+
content_type 'application/rdf+xml',
|
24
|
+
extensions: [:rdf, :owl],
|
25
|
+
uri: 'http://www.w3.org/ns/formats/RDF_XML'
|
24
26
|
content_encoding 'utf-8'
|
25
27
|
|
26
28
|
reader { RDF::RDFXML::Reader }
|
@@ -25,7 +25,7 @@ module RDF::RDFXML
|
|
25
25
|
|
26
26
|
# Create a new element child of an existing node
|
27
27
|
def create_node(name, children)
|
28
|
-
native = ::Nokogiri::XML::Element.new(name, @node)
|
28
|
+
native = ::Nokogiri::XML::Element.new(name, @node.document)
|
29
29
|
children.each do |c|
|
30
30
|
native.add_child(c.node)
|
31
31
|
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,15 +47,25 @@ 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
|
-
# @see
|
68
|
+
# @see https://ruby-rdf.github.io/rdf/RDF/Writer#options-class_method
|
59
69
|
def self.options
|
60
70
|
super + [
|
61
71
|
RDF::CLI::Option.new(
|
@@ -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.2.
|
4
|
+
version: 3.2.2
|
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:
|
12
|
+
date: 2023-07-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rdf
|
@@ -40,33 +40,33 @@ dependencies:
|
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '3.2'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: htmlentities
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '3
|
48
|
+
version: '4.3'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '3
|
55
|
+
version: '4.3'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
57
|
+
name: builder
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '3.2'
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '3.2'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: json-ld
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,18 +192,22 @@ files:
|
|
192
192
|
- UNLICENSE
|
193
193
|
- VERSION
|
194
194
|
- lib/rdf/rdfxml.rb
|
195
|
+
- lib/rdf/rdfxml/extensions.rb
|
195
196
|
- lib/rdf/rdfxml/format.rb
|
196
|
-
- lib/rdf/rdfxml/patches/nokogiri_hacks.rb
|
197
197
|
- lib/rdf/rdfxml/reader.rb
|
198
198
|
- lib/rdf/rdfxml/reader/nokogiri.rb
|
199
199
|
- lib/rdf/rdfxml/reader/rexml.rb
|
200
200
|
- lib/rdf/rdfxml/version.rb
|
201
201
|
- lib/rdf/rdfxml/writer.rb
|
202
|
-
- lib/rdf/rdfxml/writer/haml_templates.rb
|
203
202
|
homepage: https://github.com/ruby-rdf/rdf-rdfxml
|
204
203
|
licenses:
|
205
204
|
- Unlicense
|
206
|
-
metadata:
|
205
|
+
metadata:
|
206
|
+
documentation_uri: https://ruby-rdf.github.io/rdf-rdfxml
|
207
|
+
bug_tracker_uri: https://github.com/ruby-rdf/rdf-rdfxml/issues
|
208
|
+
homepage_uri: https://github.com/ruby-rdf/rdf-rdfxml
|
209
|
+
mailing_list_uri: https://lists.w3.org/Archives/Public/public-rdf-ruby/
|
210
|
+
source_code_uri: https://github.com/ruby-rdf/rdf-rdfxml
|
207
211
|
post_install_message:
|
208
212
|
rdoc_options: []
|
209
213
|
require_paths:
|
@@ -219,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
223
|
- !ruby/object:Gem::Version
|
220
224
|
version: '0'
|
221
225
|
requirements: []
|
222
|
-
rubygems_version: 3.3.
|
226
|
+
rubygems_version: 3.3.26
|
223
227
|
signing_key:
|
224
228
|
specification_version: 4
|
225
229
|
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
|