Class: RDF::RDFXML::Writer

Inherits:
RDF::RDFa::Writer show all
Includes:
Util::Logger
Defined in:
vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb,
vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer/haml_templates.rb

Overview

An RDF/XML serialiser in Ruby

Note that the natural interface is to write a whole graph at a time. Writing statements or Triples will create a graph to add them to and then serialize the graph.

The writer will add prefix definitions, and use them for creating @prefix definitions, and minting QNames

Examples:

Obtaining a RDF/XML writer class

RDF::Writer.for(:rdf)         #=> RDF::RDFXML::Writer
RDF::Writer.for("etc/test.rdf")
RDF::Writer.for(file_name: "etc/test.rdf")
RDF::Writer.for(file_extension: "rdf")
RDF::Writer.for(content_type: "application/rdf+xml")

Serializing RDF graph into an RDF/XML file

RDF::RDFXML::Write.open("etc/test.rdf") do |writer|
  writer << graph
end

Serializing RDF statements into an RDF/XML file

RDF::RDFXML::Writer.open("etc/test.rdf") do |writer|
  graph.each_statement do |statement|
    writer << statement
  end
end

Serializing RDF statements into an RDF/XML string

RDF::RDFXML::Writer.buffer do |writer|
  graph.each_statement do |statement|
    writer << statement
  end
end

Creating @base and @prefix definitions in output

RDF::RDFXML::Writer.buffer(base_uri: "http://example.com/", prefixes: {
    nil => "http://example.com/ns#",
    foaf: "http://xmlns.com/foaf/0.1/"}
) do |writer|
  graph.each_statement do |statement|
    writer << statement
  end
end

Author:

Constant Summary

VALID_ATTRIBUTES =
[:none, :untyped, :typed]
BASE_HAML =

The default set of HAML templates used for RDFa code generation

{
 identifier: "base", 
  # Document
  # Locals: lang, title, prefix, base, subjects
  # Yield: subjects.each
  doc: %q(
    = %(<?xml version='1.0' encoding='utf-8' ?>)
    - if stylesheet
      = %(<?xml-stylesheet type="text/xsl" href="#{stylesheet}"?>)
    %rdf:RDF{prefix_attrs.merge("xml:lang" => lang, "xml:base" => base)}
      - subjects.each do |subject|
        != yield(subject)
  ),

  # Output for non-leaf resources
  # Note that @about may be omitted for Nodes that are not referenced
  #
  # If _rel_ and _resource_ are not nil, the tag will be written relative
  # to a previous subject. If _element_ is :li, the tag will be written
  # with <li> instead of <div>.
  #
  # Locals: subject, typeof, predicates, rel, element, inlist, attr_props
  # Yield: predicates.each
  subject: %q(
    - first_type, *types = typeof.to_s.split(' ')
    - (types.unshift(first_type); first_type = nil) if first_type && (first_type.include?('/') || first_type.start_with?('_:'))
    - first_type ||= get_qname(RDF.Description)
    - first_type = first_type[1..-1] if first_type.to_s.start_with?(":")
    - attr_props = attr_props.merge(get_qname(RDF.nodeID) => subject.id) if subject.node? && ref_count(subject) >= 1
    - attr_props = attr_props.merge(get_qname(RDF.about) => relativize(subject)) if subject.uri?
    - haml_tag(first_type, attr_props) do
      - types.each do |type|
        - expanded_type = expand_curie(type)
        - if expanded_type.start_with?('_:')
          - haml_tag(get_qname(RDF.type), "rdf:nodeID" => expanded_type[2..-1])
        -else
          - haml_tag(get_qname(RDF.type), "rdf:resource" => expanded_type)
      - predicates.each do |p|
        = yield(p)
  ),

  # Output for single-valued properties
  # Locals: predicate, object, inlist
  # Yields: object
  # If nil is returned, render as a leaf
  # Otherwise, render result
  property_value: %q(
  - if recurse && res = yield(object)
    - haml_tag(property) do
      = res
  - elsif object.literal? && object.datatype == RDF.XMLLiteral
    - haml_tag(property, :"<", "rdf:parseType" => "Literal") do
      = object.value
  - elsif object.literal?
    - haml_tag(property, :"<", "xml:lang" => object.language, "rdf:datatype" => (object.datatype unless object.plain?)) do
      = object.value.to_s.encode(xml: :text)
  - elsif object.node?
    - haml_tag(property, :"/", "rdf:nodeID" => object.id)
  - else
    - haml_tag(property, :"/", "rdf:resource" => relativize(object))
  ),

  # Outpust for a list
  # Locals: predicate, list
  # Yields: object
  # If nil is returned, render as a leaf
  # Otherwise, render result
  collection: %q(
    - haml_tag(property, get_qname(RDF.parseType) => "Collection") do
      - list.each do |object|
        - if recurse && res = yield(object)
          = res
        - elsif object.node?
          - haml_tag(get_qname(RDF.Description), :"/", "rdf:nodeID" => (object.id if ref_count(object) > 1))
        - else
          - haml_tag(get_qname(RDF.Description), :"/", "rdf:about" => relativize(object))
  ),
}
HAML_TEMPLATES =
{base: BASE_HAML}
DEFAULT_HAML =
BASE_HAML

Constants inherited from RDF::RDFa::Writer

RDF::RDFa::Writer::DISTILLER_HAML, RDF::RDFa::Writer::HAML_OPTIONS, RDF::RDFa::Writer::MIN_HAML

Instance Attribute Summary

Attributes inherited from RDF::RDFa::Writer

#base_uri, #graph, #heading_predicates, #predicate_order, #top_classes

Attributes inherited from Writer

#options

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util::Logger

#log_debug, #log_depth, #log_error, #log_fatal, #log_info, #log_recover, #log_recovering?, #log_statistics, #log_warn, #logger

Methods inherited from RDF::RDFa::Writer

#get_content, #get_curie, #get_dt_curie, #get_lang, #get_predicate_name, #get_value, #order_properties, #order_subjects, #predicate, #properties_for_subject, #render_subject_template, #reset, #subject, #type_of, #write_triple

Methods inherited from Writer

#base_uri, buffer, #canonicalize?, dump, each, #encoding, #escaped, #flush, for, format, #format_list, #format_literal, #format_node, #format_term, #format_uri, #node_id, open, #prefix, #prefixes, #prefixes=, #puts, #quoted, #to_sym, to_sym, #uri_for, #validate?, #write_comment, #write_prologue, #write_statement, #write_triple, #write_triples

Methods included from Util::Aliasing::LateBound

#alias_method

Methods included from Writable

#<<, #insert, #insert_graph, #insert_reader, #insert_statement, #insert_statements, #writable?

Constructor Details

#initialize(output = $stdout, options = {}) {|writer| ... } ⇒ Writer

Initializes the RDF/XML writer instance.

Parameters:

  • output (IO, File) (defaults to: $stdout)

    the output stream

  • options (Hash{Symbol => Object}) (defaults to: {})

    any additional options

Options Hash (options):

  • :canonicalize (Boolean) — default: false

    whether to canonicalize literals when serializing

  • :prefixes (Hash) — default: Hash.new

    the prefix mappings to use (not supported by all writers)

  • :base_uri (#to_s) — default: nil

    the base URI to use when constructing relative URIs

  • :max_depth (Integer) — default: 10

    Maximum depth for recursively defining resources

  • :lang (#to_s) — default: nil

    Output as root xml:lang attribute, and avoid generation xml:lang where possible

  • :attributes (Symbol) — default: nil

    How to use XML attributes when serializing, one of :none, :untyped, :typed. The default is :none.

  • :standard_prefixes (Boolean) — default: false

    Add standard prefixes to prefixes, if necessary.

  • :default_namespace (String) — default: nil

    URI to use as default namespace, same as prefix(nil)

  • :stylesheet (String) — default: nil

    URI to use as @href for output stylesheet processing instruction.

Yields:

  • (writer)

Yield Parameters:



116
117
118
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 116

def initialize(output = $stdout, options = {}, &block)
  super
end

Class Method Details

.optionsObject

RDF/XML Writer options



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 59

def self.options
  super + [
    RDF::CLI::Option.new(
      symbol: :attributes,
      datatype: %w(none untyped typed),
      on: ["--attributes ATTRIBUTES",  %w(none untyped typed)],
      description: "How to use XML attributes when serializing, one of :none, :untyped, :typed. The default is :none.") {|arg| arg.to_sym},
    RDF::CLI::Option.new(
      symbol: :default_namespace,
      datatype: RDF::URI,
      on: ["--default-namespace URI", :REQUIRED],
      description: "URI to use as default namespace, same as prefixes.") {|arg| RDF::URI(arg)},
    RDF::CLI::Option.new(
      symbol: :lang,
      datatype: String,
      on: ["--lang"],
      description: "Output as root @lang attribute, and avoid generation _@lang_ where possible."),
    RDF::CLI::Option.new(
      symbol: :max_depth,
      datatype: Integer,
      on: ["--max-depth"],
      description: "Maximum depth for recursively defining resources, defaults to 3.") {|arg| arg.to_i},
    RDF::CLI::Option.new(
      symbol: :stylesheet,
      datatype: RDF::URI,
      on: ["--stylesheet URI", :REQUIRED],
      description: "URI to use as @href for output stylesheet processing instruction.") {|arg| RDF::URI(arg)},
  ]
end

Instance Method Details

#ensure_curie(resource) ⇒ Object (protected)

Make sure a CURIE is defined



390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 390

def ensure_curie(resource)
  if get_curie(resource) == resource.to_s || get_curie(resource).split(':', 2).last =~ /[\.#]/
    uri = resource.to_s
    # No vocabulary found, invent one
    # Add bindings for predicates not already having bindings
    # From RDF/XML Syntax and Processing:
    #   An XML namespace-qualified name (QName) has restrictions on the legal characters such that not all property URIs can be expressed as these names. It is recommended that implementors of RDF serializers, in order to break a URI into a namespace name and a local name, split it after the last XML non-NCName character, ensuring that the first character of the name is a Letter or '_'. If the URI ends in a non-NCName character then throw a "this graph cannot be serialized in RDF/XML" exception or error.
    separation = uri.rindex(%r{[^a-zA-Z_0-9-][a-zA-Z_][a-z0-9A-Z_-]*$})
    return @uri_to_prefix[uri] = nil unless separation
    base_uri = uri.to_s[0..separation]
    suffix = uri.to_s[separation+1..-1]
    @gen_prefix = @gen_prefix ? @gen_prefix.succ : "ns0"
    log_debug {"ensure_curie: generated prefix #{@gen_prefix} for #{base_uri}"}
    @uri_to_prefix[base_uri] = @gen_prefix
    @uri_to_term_or_curie[uri] = "#{@gen_prefix}:#{suffix}"
    prefix(@gen_prefix, base_uri)
    get_curie(resource)
  end
end

#expand_curie(curie) ⇒ RDF::URI (protected)

Undo CURIE

Returns:



420
421
422
423
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 420

def expand_curie(curie)
  pfx, suffix = curie.split(":", 2)
  prefix(pfx) ? prefix(pfx) + suffix : curie
end

#get_qname(uri) ⇒ Object (protected)

Turn CURIE into a QNAME



372
373
374
375
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 372

def get_qname(uri)
  curie = get_curie(uri)
  curie.start_with?(":") ? curie[1..-1] : curie
end

#haml_templateHash<Symbol => String>

Returns:



121
122
123
124
125
126
127
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 121

def haml_template
  return @haml_template if @haml_template
  case @options[:haml]
  when Hash             then @options[:haml]
  else                       DEFAULT_HAML
  end
end

#predicate_as_attribute?(prop, object) ⇒ Boolean (protected)

See if we can serialize as attribute.

  • untyped attributes that aren't duplicated where xml:lang == @lang
  • typed attributes that aren't duplicated if @dt_as_attr is true
  • rdf:type

Returns:

  • (Boolean)


198
199
200
201
202
203
204
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 198

def predicate_as_attribute?(prop, object)
  [:untyped, :typed].include?(@attributes) && (
    prop == RDF.type ||
    [:typed].include?(@attributes) && object.literal? && object.typed? ||
    (object.literal? && object.simple? || @lang && object.language.to_s == @lang.to_s)
  )
end

#prefix_attrsHash{String => String} (protected)

XML namespace attributes for defined prefixes

Returns:



338
339
340
341
342
343
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 338

def prefix_attrs
  prefixes.inject({}) do |memo, (k, v)|
    memo[k ? "xmlns:#{k}" : "xmlns"] = v.to_s
    memo
  end
end

#preprocessignored (protected)

Perform any preprocessing of statements required

Returns:

  • (ignored)


347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 347

def preprocess
  # Load defined prefixes
  (@options[:prefixes] || {}).each_pair do |k, v|
    @uri_to_prefix[v.to_s] = k
  end
  @options[:prefixes] = {}  # Will define actual used when matched

  prefix(:rdf, RDF.to_uri)
  @uri_to_prefix[RDF.to_uri.to_s] = :rdf
  if base_uri || @options[:lang]
    prefix(:xml, RDF::XML)
    @uri_to_prefix[RDF::XML.to_s] = :xml
  end

  if @options[:default_namespace]
    @uri_to_prefix[@options[:default_namespace]] = nil
    prefix(nil, @options[:default_namespace])
  end

  # Process each statement to establish CURIEs and Terms
  @graph.each {|statement| preprocess_statement(statement)}
end

#preprocess_statement(statement) ⇒ Object (protected)

Perform any statement preprocessing required. This is used to perform reference counts and determine required prefixes.

For RDF/XML, make sure that all predicates have CURIEs

Parameters:



381
382
383
384
385
386
387
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 381

def preprocess_statement(statement)
  super

  # Invent a prefix for the predicate, if necessary
  ensure_curie(statement.predicate)
  ensure_curie(statement.object) if statement.predicate == RDF.type
end

#relativize(uri) ⇒ String (protected)

If base_uri is defined, use it to try to make uri relative

Parameters:

  • uri (#to_s)

Returns:



413
414
415
416
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 413

def relativize(uri)
  uri = expand_curie(uri.to_s)
  base_uri ? uri.sub(base_uri.to_s, "") : uri
end

#render_collection(predicate, list, options = {}) {|object| ... } ⇒ Object (protected)

Render a collection, which may be included in a property declaration, or may be recursive within another collection

Parameters:

Yields:

  • object Yields object, unless it is an included list

Yield Parameters:

Yield Returns:

  • (String, nil)

    The block should only return a string for recursive object definitions.

Returns:

  • String The rendered collection is returned as a string



322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 322

def render_collection(predicate, list, options = {}, &block)
  template = options[:haml] || haml_template[:collection]

  options = {
    list:       list,
    predicate:  predicate,
    property:   get_qname(predicate),
    recurse:    log_depth <= @max_depth,
  }.merge(options)
  hamlify(template, options) do |object|
    yield object
  end
end

#render_document(subjects, options = {}) {|subject| ... } ⇒ Object (protected)

Render document using haml_template[:doc]. Yields each subject to be rendered separately.

For RDF/XML pass along a stylesheet option.

Parameters:

  • subjects (Array<RDF::Resource>)

    Ordered list of subjects. Template must yield to each subject, which returns the serialization of that subject (@see #subject_template)

  • options (Hash{Symbol => Object}) (defaults to: {})

    Rendering options passed to Haml render.

Options Hash (options):

  • base (RDF::URI) — default: nil

    Base URI added to document, used for shortening URIs within the document.

  • language (Symbol, String) — default: nil

    Value of @lang attribute in document, also allows included literals to omit an @lang attribute if it is equivalent to that of the document.

  • title (String) — default: nil

    Value of html>head>title element.

  • prefix (String) — default: nil

    Value of @prefix attribute.

  • haml (String) — default: haml_template[:doc]

    Haml template to render.

Yields:

  • (subject)

    Yields each subject

Yield Parameters:

Yield Returns:

  • (:ignored)

Returns:

  • String The rendered document is returned as a string



231
232
233
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 231

def render_document(subjects, options = {}, &block)
  super(subjects, options.merge(stylesheet: @options[:stylesheet]), &block)
end

#render_property(predicate, objects, options = {}) {|object, inlist| ... } ⇒ Object (protected)

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

For RDF/XML, pass the :no_list_literals option onto the RDFa implementation because of special considerations for lists in RDF/XML.

If a multi-valued property definition is not found within the template, the writer will use the single-valued property definition multiple times.

Parameters:

  • predicate (Array<RDF::Resource>)

    Predicate to render.

  • objects (Array<RDF::Resource>)

    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.

  • options (Hash{Symbol => Object}) (defaults to: {})

    Rendering options passed to Haml render.

Options Hash (options):

  • :haml (String) — default: haml_template[:property_value], haml_template[:property_values]

    Haml template to render. Otherwise, uses haml_template[:property_value] or haml_template[:property_values] depending on the cardinality of objects.

  • :no_list_literals (Boolean)

    Do not serialize as a list if any elements are literal.

Yields:

  • object, inlist Yields object and if it is contained in a list.

Yield Parameters:

Yield Returns:

  • (String, nil)

    The block should only return a string for recursive object definitions.

Returns:

  • String The rendered document is returned as a string



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 259

def render_property(predicate, objects, options = {}, &block)
  log_debug {"render_property(#{predicate}): #{objects.inspect}, #{options.inspect}"}
  # If there are multiple objects, and no :property_values is defined, call recursively with
  # each object

  template = options[:haml]
  template ||= haml_template[:property_value]

  # Separate out the objects which are lists and render separately
  lists = objects.
    select(&:node?).
    map {|o| RDF::List.new(subject: o, graph: @graph)}.
    select {|l| l.valid? && l.none?(&:literal?)}

  unless lists.empty?
    # Render non-list objects
    log_debug {"properties with lists: #{lists} non-lists: #{objects - lists.map(&:subject)}"}
    nl = log_depth {render_property(predicate, objects - lists.map(&:subject), options, &block)} unless objects == lists.map(&:subject)
    return nl.to_s + lists.map do |list|
      # Render each list as multiple properties and set :inlist to true
      list.each_statement {|st| subject_done(st.subject)}

      log_debug {"list: #{list.inspect} #{list.to_a}"}
      log_depth do
        render_collection(predicate, list, options) do |object|
          yield(object, true) if block_given?
        end
      end
    end.join(" ")
  end

  if objects.length > 1
    # Render each property using property_value template
    objects.map do |object|
      log_depth {render_property(predicate, [object], options, &block)}
    end.join(" ")
  else
    log_fatal("Missing property template", exception:  RDF::WriterError) if template.nil?

    options = {
      object:     objects.first,
      predicate:  predicate,
      property:   get_qname(predicate),
      recurse:    log_depth <= @max_depth
    }.merge(options)
    hamlify(template, options, &block)
  end
end

#render_subject(subject, predicates, options = {}) {|predicate| ... } ⇒ Object (protected)

Render a subject using haml_template[:subject].

The subject template may be called either as a top-level element, or recursively under another element if the rel local is not nil.

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.

Yields each predicate/property to be rendered separately (@see #render_property_value and #render_property_values).

Return Haml template for document from haml_template[:subject]

Parameters:

  • subject (Array<RDF::Resource>)

    Subject to render

  • predicates (Array<RDF::Resource>)

    Predicates of subject. Each property is yielded for separate rendering.

  • options (Hash{Symbol => Object}) (defaults to: {})

    Rendering options passed to Haml render.

Options Hash (options):

  • about (String) — default: nil

    About description, a CURIE, URI or Node definition. May be nil if no @about is rendered (e.g. unreferenced Nodes)

  • resource (String) — default: nil

    Resource description, a CURIE, URI or Node definition. May be nil if no @resource is rendered

  • rel (String) — default: nil

    Optional @rel property description, a CURIE, URI or Node definition.

  • typeof (String) — default: nil

    RDF type as a CURIE, URI or Node definition. If :about is nil, this defaults to the empty string ("").

  • element (:li, nil) — default: nil

    Render with <li>, otherwise with template default.

  • haml (String) — default: haml_template[:subject]

    Haml template to render.

Yields:

Yield Parameters:

Yield Returns:

  • (:ignored)

Returns:

  • String The rendered document is returned as a string



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 173

def render_subject(subject, predicates, options = {}, &block)
  # extract those properties that can be rendered as attributes
  attr_props = if [:untyped, :typed].include?(@attributes)
    options[:property_values].inject({}) do |memo, (prop, values)|
      object = values.first
      if values.length == 1 &&
        object.literal? &&
        (object.plain? || @attributes == :typed) &&
        get_lang(object).nil?

        memo[get_qname(RDF::URI(prop))] = object.value
      end
      memo
    end
  else
    {}
  end

  predicates -= attr_props.keys.map {|k| expand_curie(k).to_s}
  super(subject, predicates, options.merge(attr_props: attr_props), &block)
end

#write_epilogueObject



129
130
131
132
133
134
135
# File 'vendor/bundler/ruby/2.5.0/bundler/gems/rdf-rdfxml-dd99a73f7b99/lib/rdf/rdfxml/writer.rb', line 129

def write_epilogue
  @force_RDF_about = {}
  @max_depth = @options.fetch(:max_depth, 10)
  @attributes = @options.fetch(:attributes, :none)

  super
end