lib/resync/xml.rb in resync-0.3.0 vs lib/resync/xml.rb in resync-0.3.1

- old
+ new

@@ -1,8 +1,10 @@ require 'uri' require 'time' require 'xml/mapping' +require 'xml/mapping_extensions' + require_relative 'types' module Resync # Helper methods and modules related to reading and writing XML. module XML @@ -55,157 +57,44 @@ arg.respond_to?(:eof?)) end private_class_method :can_parse # ------------------------------------------------------------ - # Time - - # Maps +Time+ objects. - class TimeNode < ::XML::Mapping::SingleAttributeNode - def initialize(*args) - path, *args = super(*args) - @path = ::XML::XXPath.new(path) - args - end - - # Implements +::XML::Mapping::SingleAttributeNode#extract_attr_value+. - def extract_attr_value(xml) - value = default_when_xpath_err { @path.first(xml).text } - value ? Time.iso8601(value).utc : nil - end - - # Implements +::XML::Mapping::SingleAttributeNode#set_attr_value+. - def set_attr_value(xml, value) - @path.first(xml, ensure_created: true).text = value.iso8601 - end - end - - ::XML::Mapping.add_node_class TimeNode - - # ------------------------------------------------------------ - # URI - - # Maps +URI+ objects. - class UriNode < ::XML::Mapping::SingleAttributeNode - def initialize(*args) - path, *args = super(*args) - @path = ::XML::XXPath.new(path) - args - end - - # Implements +::XML::Mapping::SingleAttributeNode#extract_attr_value+. - def extract_attr_value(xml) - val = default_when_xpath_err { @path.first(xml).text } - URI(val.strip) - end - - # Implements +::XML::Mapping::SingleAttributeNode#set_attr_value+. - def set_attr_value(xml, value) - @path.first(xml, ensure_created: true).text = value.to_s - end - end - - ::XML::Mapping.add_node_class UriNode - - # ------------------------------------------------------------ - # Resync::Types - - class EnumNode < ::XML::Mapping::SingleAttributeNode - def initialize(*args) - path, *args = super(*args) - @path = ::XML::XXPath.new(path) - args - end - - # Implements +::XML::Mapping::SingleAttributeNode#extract_attr_value+. - def extract_attr_value(xml) - enum_class = self.class::ENUM_CLASS - enum_class.parse(default_when_xpath_err { @path.first(xml).text }) - end - - # Implements +::XML::Mapping::SingleAttributeNode#set_attr_value+. - def set_attr_value(xml, value) - @path.first(xml, ensure_created: true).text = value.to_s - end - end - - # ------------------------------------------------------------ # Resync::Types::Change # Maps +Resync::Types::Change+ values. - class ChangeNode < EnumNode + class ChangeNode < ::XML::MappingExtensions::EnumNodeBase ENUM_CLASS = Resync::Types::Change end ::XML::Mapping.add_node_class ChangeNode # ------------------------------------------------------------ # Resync::Types::Changefreq # Maps +Resync::Types::ChangeFrequency+ values. - class ChangefreqNode < EnumNode + class ChangefreqNode < ::XML::MappingExtensions::EnumNodeBase ENUM_CLASS = Resync::Types::ChangeFrequency end ::XML::Mapping.add_node_class ChangefreqNode # ------------------------------------------------------------ - # MIME::Type - - # Maps +MIME::Type+ values. - class MimeTypeNode < ::XML::Mapping::SingleAttributeNode - def initialize(*args) - path, *args = super(*args) - @path = ::XML::XXPath.new(path) - args - end - - # Implements +::XML::Mapping::SingleAttributeNode#extract_attr_value+. - def extract_attr_value(xml) - mime_type = default_when_xpath_err { @path.first(xml).text } - return nil unless mime_type - return mime_type if mime_type.is_a?(MIME::Type) - - mt = MIME::Types[mime_type].first - return mt if mt - - MIME::Type.new(mime_type) - end - - # Implements +::XML::Mapping::SingleAttributeNode#set_attr_value+. - def set_attr_value(xml, value) - @path.first(xml, ensure_created: true).text = value.to_s - end - end - - ::XML::Mapping.add_node_class MimeTypeNode - - # ------------------------------------------------------------ # Whitespace-separated hashcode list # Maps the whitespace-separated list of hash codes in a +<rs:ln>+ # or +<rs:md>+ tag to a hash of digest values keyed by hash algorithm. # (See {Resync::Descriptor#hashes}.) - class HashCodesNode < ::XML::Mapping::SingleAttributeNode - def initialize(*args) - path, *args = super(*args) - @path = ::XML::XXPath.new(path) - args - end + class HashCodesNode < ::XML::MappingExtensions::NodeBase - # Implements +::XML::Mapping::SingleAttributeNode#extract_attr_value+. - def extract_attr_value(xml) - hashes = default_when_xpath_err { @path.first(xml).text } - return {} unless hashes - return hashes if hashes.is_a?(Hash) - hashes.split(/[[:space:]]+/).map { |hash| hash.split(':') }.to_h + def to_value(xml_text) + return {} unless xml_text + return xml_text if xml_text.is_a?(Hash) + xml_text.split(/[[:space:]]+/).map { |hash| hash.split(':') }.to_h end - # Implements +::XML::Mapping::SingleAttributeNode#set_attr_value+. - def set_attr_value(xml, value) - return if value.empty? - hash_str = value.map { |k, v| "#{k}:#{v}" }.join(' ') - @path.first(xml, ensure_created: true).text = hash_str + def to_xml_text(value) + value.map { |k, v| "#{k}:#{v}" }.join(' ') if value && !value.empty? end end ::XML::Mapping.add_node_class HashCodesNode