Module: RubyXL::OOXMLObjectInstanceMethods

Included in:
OOXMLContainerObject, OOXMLObject
Defined in:
lib/rubyXL/objects/ooxml_object.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#local_namespacesObject

Returns the value of attribute local_namespaces.



218
219
220
# File 'lib/rubyXL/objects/ooxml_object.rb', line 218

def local_namespaces
  @local_namespaces
end

Class Method Details

.included(klass) ⇒ Object



220
221
222
# File 'lib/rubyXL/objects/ooxml_object.rb', line 220

def self.included(klass)
  klass.extend RubyXL::OOXMLObjectClassMethods
end

Instance Method Details

#==(other) ⇒ Object



258
259
260
261
262
# File 'lib/rubyXL/objects/ooxml_object.rb', line 258

def ==(other)
  other.is_a?(self.class) &&
    obtain_class_variable(:@@ooxml_attributes).all? { |_k, v| self.send(v[:accessor]) == other.send(v[:accessor]) } &&
    obtain_class_variable(:@@ooxml_child_nodes).all? { |_k, v| self.send(v[:accessor]) == other.send(v[:accessor]) }
end

#before_write_xmlObject

Subclass provided filter to perform last-minute operations (cleanup, count, etc.) immediately prior to write, along with option to terminate the actual write if false is returned (for example, to avoid writing the collection’s root node if the collection is empty).



357
358
359
360
361
362
363
364
# File 'lib/rubyXL/objects/ooxml_object.rb', line 357

def before_write_xml
  #TODO# This will go away once containers are fully implemented.
  child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
  child_nodes.each_pair { |_child_node_name, child_node_params|
    self.count = self.send(child_node_params[:accessor]).size if child_node_params[:is_array] == :with_count
  }
  true
end

#index_in_collectionObject

Prototype method. For sparse collections (Rows, Cells, etc.) must return index at which this object is expected to reside in the collection. If nil is returned, then object is simply added to the end of the collection.



345
346
347
# File 'lib/rubyXL/objects/ooxml_object.rb', line 345

def index_in_collection
  nil
end

#initialize(params = nil) ⇒ Object



229
230
231
232
233
234
235
236
237
238
# File 'lib/rubyXL/objects/ooxml_object.rb', line 229

def initialize(params = nil)
  @local_namespaces = nil
  params ||= {}

  obtain_class_variable(:@@ooxml_attributes).each_value { |v|
    instance_variable_set("@#{v[:accessor]}", params[v[:accessor]]) unless v[:computed]
  }

  init_child_nodes(params)
end

#write_xml(xml = nil, node_name_override = nil) ⇒ Object

Recursively write the OOXML object and all its children out as Nokogiri::XML. Immediately before the actual generation, before_write_xml() is called to perform last-minute cleanup and validation operations; if it returns false, an empty string is returned (rather than nil, so Nokogiri::XML’s << operator can be used without additional nil checking)

Parameters

  • xml - Base Nokogiri::XML object used for building. If omitted, a blank document will be generated.

  • node_name_override - if present, is used instead of the default element name for this object provided by define_element_name

Examples

obj.write_xml()

Creates a new empty Nokogiri::XML, populates it with the OOXML structure as described in the respective definition, and returns the resulting Nokogiri::XML object.

obj.write_xml(seed_xml)

Using the passed-in Nokogiri xml object, creates a new element corresponding to obj according to its definition, along with all its properties and children, and returns the newly created element.

obj.write_xml(seed_xml, 'overriden_element_name')

Same as above, but uses the passed-in node_name_override as the new element name, instead of its default name set by define_element_name.



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
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'lib/rubyXL/objects/ooxml_object.rb', line 278

def write_xml(xml = nil, node_name_override = nil)
  if xml.nil? then
    seed_xml = Nokogiri::XML('<?xml version = "1.0" standalone ="yes"?>')
    seed_xml.encoding = 'UTF-8'

    if Nokogiri.jruby? then # Issue 188 workaround for JRuby
      seed_xml.to_java.strict_error_checking = false
    end

    result = self.write_xml(seed_xml)
    return result if result == ''
    seed_xml << result
    return seed_xml.to_xml({ :indent => 0, :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML })
  end

  return '' unless before_write_xml

  attrs = {}

  obtain_class_variable(:@@ooxml_attributes).each_pair { |k, v|
    val = self.send(v[:accessor])

    if val.nil? then
      next unless v[:required]
      val = v[:default]
    end

    val = val &&
            case v[:attr_type]
            when :bool   then val ? '1' : '0'
            when :double then val.to_s.gsub(/\.0*\Z/, '') # Trim trailing zeroes
            else val
            end

    attrs[k] = val
  }

  element_text = attrs.delete('_')
  elem = xml.create_element(node_name_override || obtain_class_variable(:@@ooxml_tag_name), attrs, element_text)

  # First, populate namespaces from the original document
  @local_namespaces&.each_pair { |href, prefix| elem.add_namespace_definition(prefix, href) }

  # Then, add defaults. Note that if some namespace prefix was already set, Nokogiri will NOT change that namespace.
  obtain_class_variable(:@@ooxml_namespaces).each_pair { |href, prefix| elem.add_namespace_definition(prefix, href) }

  child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
  child_nodes.each_pair { |child_node_name, child_node_params|
    node_obj = get_node_object(child_node_params)
    next if node_obj.nil?

    if node_obj.respond_to?(:write_xml) && !node_obj.equal?(self) then
      # If child node is either +OOXMLObject+, or +OOXMLContainerObject+ on its first (envelope) pass,
      # serialize that object.
      elem << node_obj.write_xml(xml, child_node_name)
    else
      # If child node is either vanilla +Array+, or +OOXMLContainerObject+ on its seconds (content) pass,
      # serialize its members.
      node_obj.each { |item| elem << item.write_xml(xml, child_node_name) unless item.nil? }
    end
  }
  elem
end