# frozen_string_literal: true module Nanaimo class Writer # Transforms native ruby objects or Plist objects into their XML Plist # string representation. # class XMLWriter < Writer autoload :Base64, 'base64' autoload :Date, 'date' autoload :DateTime, 'date' def write write_xml_header write_object(@plist.root_object) write_newline write_xml_footer end private def plist_format :xml end def write_object(object) case object when Float, Integer write_number(object) when Time, Date, DateTime write_date(object) when true, false write_boolean(object) else super end end def write_xml_header output << <<-EOS EOS end def write_xml_footer output << <<-EOS EOS end def write_annotation(_) end def write_number(object) type = object.integer? ? 'integer' : 'real' output << "<#{type}>#{object}" end def write_boolean(object) output << "<#{object}/>" end def write_date(object) output << '' << object.iso8601 << '' end def write_string(object) output << '' << Unicode.xml_escape_string(value_for(object)) << '' end def write_quoted_string(object) write_string(object) end def write_data(object) output << '' data = Base64.encode64(value_for(object)).delete("\n") data = data.scan(/.{1,76}/).join("\n") if pretty output << data << '' end def write_array(object) return output << '' if value_for(object).empty? super end def write_array_start output << '' write_newline if newlines push_indent! end def write_array_end pop_indent! write_indent output << '' end def write_array_element(object) write_indent write_object(object) write_newline end def write_dictionary(object) object = value_for(object) return output << '' if object.empty? keys = object.keys.sort_by(&:to_s) object = keys.each_with_object({}) do |key, hash| hash[key.to_s] = object[key] end super(object) end def write_dictionary_start output << '' write_newline if newlines push_indent! end def write_dictionary_end pop_indent! write_indent output << '' end def write_dictionary_key_value_pair(key, value) write_indent output << '' << Unicode.xml_escape_string(value_for(key)) << '' write_newline write_indent write_object(value) write_newline end end end end