lib/happymapper.rb
#
# Create an xml representation of the specified class based on defined
# HappyMapper elements and attributes. The method is defined in a way
# that it can be called recursively by classes that are also HappyMapper
# classes, allowing for the composition of classes.
#
Create an xml representation of the specified class based on defined
HappyMapper elements and attributes. The method is defined in a way
that it can be called recursively by classes that are also HappyMapper
classes, allowing for the composition of classes.
Create an xml representation of the specified class based on defined HappyMapper elements and attributes . The method is defined in a way that it can be called recursively by classes that are also HappyMapper classes allowing for the composition of classes .
def to_xml(parent_node = nil, default_namespace = nil)
     Create a tag that uses the tag name of the class that has no contents
     but has the specified namespace or uses the default namespace
    current_node = XML::Node.new(self.class.tag_name)
    if parent_node
       if to_xml has been called with a parent_node that means this method
       is being called recursively (or a special case) and we want to return
       the parent_node with the new node as a child
      parent_node << current_node
    else
       If to_xml has been called without a Node (and namespace) that
       means we want to return an xml document
      write_out_to_xml = true
    end
     Add all the registered namespaces to the current node and the current node's
     root element. Without adding it to the root element it is not possible to
     parse or use xpath to find elements.
    if self.class.instance_variable_get('@registered_namespaces')
       Given a node, continue moving up to parents until there are no more parents
      find_root_node = lambda {|node| while node.parent? ; node = node.parent ; end ; node }
      root_node = find_root_node.call(current_node)
       Add the registered namespace to the found root node only if it does not already have one defined
      self.class.instance_variable_get('@registered_namespaces').each_pair do |prefix,href|
        XML::Namespace.new(current_node,prefix,href)
        XML::Namespace.new(root_node,prefix,href) unless root_node.namespaces.find_by_prefix(prefix)
      end
    end
     Determine the tag namespace if one has been specified. This value takes
     precendence over one that is handed down to composed sub-classes.
    tag_namespace = current_node.namespaces.find_by_prefix(self.class.namespace) || default_namespace
     Set the namespace of the current node to the specified namespace
    current_node.namespaces.namespace = tag_namespace if tag_namespace
     Add all the attribute tags to the current node with their namespace, if one
     is defined, or the namespace handed down to the node.
    self.class.attributes.each do |attribute|
      attribute_namespace = current_node.namespaces.find_by_prefix(attribute.options[:namespace]) || default_namespace
      value = send(attribute.method_name)
       If the attribute has a :on_save attribute defined that is a proc or
       a defined method, then call those with the current value.
      if on_save_operation = attribute.options[:on_save]
        if on_save_operation.is_a?(Proc)
          value = on_save_operation.call(value)
        elsif respond_to?(on_save_operation)
          value = send(on_save_operation,value)
        end
      end
      current_node[ "{attribute_namespace ? "{attribute_namespace.prefix}:" : ""}{attribute.tag}" ] = value.to_s
    end
     All all the elements defined (e.g. has_one, has_many, element) ...
    self.class.elements.each do |element|
      tag = element.tag || element.name
      element_namespace = current_node.namespaces.find_by_prefix(element.options[:namespace]) || tag_namespace
      value = send(element.name)
       If the element defines an :on_save lambda/proc then we will call that
       operation on the specified value. This allows for operations to be 
       performed to convert the value to a specific value to be saved to the xml.
      if on_save_operation = element.options[:on_save]
        if on_save_operation.is_a?(Proc)
          value = on_save_operation.call(value)
        elsif respond_to?(on_save_operation)
          value = send(on_save_operation,value)
        end
      end
       Normally a nil value would be ignored, however if specified then
       an empty element will be written to the xml
      if value.nil? && element.options[:state_when_nil]
        current_node << XML::Node.new(tag,nil,element_namespace)
      end
       To allow for us to treat both groups of items and singular items
       equally we wrap the value and treat it as an array.
      if value.nil?
        values = []
      elsif value.respond_to?(:to_ary) && !element.options[:single]
        values = value.to_ary
      else
        values = [value]
      end
      values.each do |item|
        if item.is_a?(HappyMapper)
           Other HappyMapper items that are convertable should not be called
           with the current node and the namespace defined for the element.
          item.to_xml(current_node,element_namespace)
        elsif item
           When a value exists we should append the value for the tag
          current_node << XML::Node.new(tag,item.to_s,element_namespace)
        else
           Normally a nil value would be ignored, however if specified then
           an empty element will be written to the xml
          current_node << XML.Node.new(tag,nil,element_namespace) if element.options[:state_when_nil]
        end
      end
    end
     Generate xml from a document if no node was passed as a parameter. Otherwise
     this method is being called recursively (or special case) and we should
     return the node with this node attached as a child.
    if write_out_to_xml
      document = XML::Document.new
      document.root = current_node
      document.to_s
    else
      parent_node
    end
  end
def to_xml ( parent_node = nil , default_namespace = nil ) current_node = XML :: Node . new ( self . class . tag_name ) if parent_node parent_node << current_node else write_out_to_xml = true end if self . class . instance_variable_get ( '@registered_namespaces' ) find_root_node = lambda { | node | while node . parent? ; node = node . parent ; end ; node } root_node = find_root_node . call ( current_node ) self . class . instance_variable_get ( '@registered_namespaces' ) . each_pair do | prefix , href | XML :: Namespace . new ( current_node , prefix , href ) XML :: Namespace . new ( root_node , prefix , href ) unless root_node . namespaces . find_by_prefix ( prefix ) end end tag_namespace = current_node . namespaces . find_by_prefix ( self . class . namespace ) || default_namespace current_node . namespaces . namespace = tag_namespace if tag_namespace self . class . attributes . each do | attribute | attribute_namespace = current_node . namespaces . find_by_prefix ( attribute . options [ :namespace ] ) || default_namespace value = send ( attribute . method_name ) if on_save_operation = attribute . options [ :on_save ] if on_save_operation . is_a? ( Proc ) value = on_save_operation . call ( value ) elsif respond_to? ( on_save_operation ) value = send ( on_save_operation , value ) end end current_node [ "#{attribute_namespace ? "#{attribute_namespace.prefix}:" : ""}#{attribute.tag}" ] = value . to_s end self . class . elements . each do | element | tag = element . tag || element . name element_namespace = current_node . namespaces . find_by_prefix ( element . options [ :namespace ] ) || tag_namespace value = send ( element . name ) if on_save_operation = element . options [ :on_save ] if on_save_operation . is_a? ( Proc ) value = on_save_operation . call ( value ) elsif respond_to? ( on_save_operation ) value = send ( on_save_operation , value ) end end if value . nil? && element . options [ :state_when_nil ] current_node << XML :: Node . new ( tag , nil , element_namespace ) end if value . nil? values = [ ] elsif value . respond_to? ( :to_ary ) && ! element . options [ :single ] values = value . to_ary else values = [ value ] end values . each do | item | if item . is_a? ( HappyMapper ) item . to_xml ( current_node , element_namespace ) elsif item current_node << XML :: Node . new ( tag , item . to_s , element_namespace ) else current_node << XML . Node . new ( tag , nil , element_namespace ) if element . options [ :state_when_nil ] end end end if write_out_to_xml document = XML :: Document . new document . root = current_node document . to_s else parent_node end end
Create an xml representation of the specified class based on defined
HappyMapper elements and attributes.
Create an xml representation of the specified class based on defined HappyMapper elements and attributes .
# # Create a tag that uses the tag name of the class that has no contents # but has the specified namespace or uses the default namespace # # # if #to_xml has been called with a parent_node that means this method # is being called recursively (or a special case) and we want to return # the parent_node with the new node as a child # # # If #to_xml has been called without a Node (and namespace) that # means we want to return an xml document # # # Add all the registered namespaces to the current node and the current node's # root element. Without adding it to the root element it is not possible to # parse or use xpath to find elements. # # Given a node, continue moving up to parents until there are no more parents # Add the registered namespace to the found root node only if it does not already have one defined # # Determine the tag namespace if one has been specified. This value takes # precendence over one that is handed down to composed sub-classes. # # Set the namespace of the current node to the specified namespace # # Add all the attribute tags to the current node with their namespace, if one # is defined, or the namespace handed down to the node. # # # If the attribute has a :on_save attribute defined that is a proc or # a defined method, then call those with the current value. # # # All all the elements defined (e.g. has_one, has_many, element) ... # # # If the element defines an :on_save lambda/proc then we will call that # operation on the specified value. This allows for operations to be  # performed to convert the value to a specific value to be saved to the xml. # # # Normally a nil value would be ignored, however if specified then # an empty element will be written to the xml # # # To allow for us to treat both groups of items and singular items # equally we wrap the value and treat it as an array. # # # Other HappyMapper items that are convertable should not be called # with the current node and the namespace defined for the element. # # # When a value exists we should append the value for the tag # # # Normally a nil value would be ignored, however if specified then # an empty element will be written to the xml # # # Generate xml from a document if no node was passed as a parameter. Otherwise # this method is being called recursively (or special case) and we should # return the node with this node attached as a child. #
parent_node
<not_specific>
default_namespace
<not_specific>