class XML::Mapping::Node

Abstract base class for all node types. As mentioned in the documentation for XML::Mapping, node types must be registered using XML::Mapping.add_node_class, and a corresponding “node factory method” (e.g. “text_node”) will then be added as a class method to your mapping classes. The node factory method is called from the body of the mapping classes as demonstrated in the examples. It creates an instance of its corresponding node type (the list of parameters to the node factory method, preceded by the owning mapping class, will be passed to the constructor of the node type) and adds it to its owning mapping class, so there is one node object per node definition per mapping class. That node object will handle all XML marshalling/unmarshalling for this node, for all instances of the mapping class. For this purpose, the marshalling and unmarshalling methods of a mapping class instance (fill_into_xml and fill_from_xml, respectively) will call ::obj_to_xml resp. ::xml_to_obj on all nodes of the mapping class, in the order of their definition, passing the REXML element the data is to be marshalled to/unmarshalled from as well as the object the data is to be read from/filled into.

Node types that map some XML data to a single attribute of their mapping class (that should be most of them) shouldn't be directly derived from this class, but rather from SingleAttributeNode.

Public Class Methods

default_obj_to_xml(obj,xml)
Alias for: obj_to_xml
default_xml_to_obj(obj,xml)
Alias for: xml_to_obj
new(owner,*args) click to toggle source

Intializer, to be called from descendant classes. owner is the mapping class this node is being defined in. It'll be stored in _@owner_. @options will be set to a (possibly empty) hash containing the option arguments passed to initialize. Options :mapping, :reader and :writer will be handled, subclasses may handle additional options. See the section on defining nodes in the README for details.

# File lib/xml/mapping/base.rb, line 550
def initialize(owner,*args)
  @owner = owner
  if Hash===args[-1]
    @options = args[-1]
    args = args[0..-2]
  else
    @options={}
  end
  @mapping = @options[:mapping] || owner.default_mapping
  owner.xml_mapping_nodes(:mapping=>@mapping) << self
  XML::Mapping::Classes_by_rootelt_names.ensure_exists owner.root_element_name, @mapping, owner
  if @options[:reader]
    # override xml_to_obj in this instance with invocation of
    # @options[:reader]
    class << self
      alias_method :default_xml_to_obj, :xml_to_obj
      def xml_to_obj(obj,xml)
        begin
          @options[:reader].call(obj,xml,self.method(:default_xml_to_obj))
        rescue ArgumentError  # thrown if @options[:reader] is a lambda (i.e. no Proc) with !=3 args (e.g. proc{...} in ruby1.8)
          @options[:reader].call(obj,xml)
        end
      end
    end
  end
  if @options[:writer]
    # override obj_to_xml in this instance with invocation of
    # @options[:writer]
    class << self
      alias_method :default_obj_to_xml, :obj_to_xml
      def obj_to_xml(obj,xml)
        begin
          @options[:writer].call(obj,xml,self.method(:default_obj_to_xml))
        rescue ArgumentError # thrown if (see above)
          @options[:writer].call(obj,xml)
        end
      end
    end
  end
  args
end
obj_to_xml(obj,xml) click to toggle source
# File lib/xml/mapping/base.rb, line 580
def obj_to_xml(obj,xml)
  begin
    @options[:writer].call(obj,xml,self.method(:default_obj_to_xml))
  rescue ArgumentError # thrown if (see above)
    @options[:writer].call(obj,xml)
  end
end
Also aliased as: default_obj_to_xml
xml_to_obj(obj,xml) click to toggle source
# File lib/xml/mapping/base.rb, line 566
def xml_to_obj(obj,xml)
  begin
    @options[:reader].call(obj,xml,self.method(:default_xml_to_obj))
  rescue ArgumentError  # thrown if @options[:reader] is a lambda (i.e. no Proc) with !=3 args (e.g. proc{...} in ruby1.8)
    @options[:reader].call(obj,xml)
  end
end
Also aliased as: default_xml_to_obj

Public Instance Methods

is_present_in?(obj) click to toggle source

tell whether this node's data is present in obj (when this method is called, obj will be an instance of the mapping class this node was defined in). This method is currently used only by ChoiceNode when writing data back to XML. See XML::Mapping::ChoiceNode#obj_to_xml.

# File lib/xml/mapping/base.rb, line 629
def is_present_in? obj
  true
end
obj_initializing(obj,mapping) click to toggle source

Called when a new instance of the mapping class this node belongs to is being initialized. obj is the instance. mapping is the mapping the initialization is happening with, if any: If the instance is being initialized as part of e.g. Class.load_from_file(name, :mapping=>:some_mapping or any other call that specifies a mapping, that mapping will be passed to this method. If the instance is being initialized normally with Class.new, mapping is nil here.

You may set up initial values for the attributes this node is responsible for here. Default implementation is empty.

# File lib/xml/mapping/base.rb, line 622
def obj_initializing(obj,mapping)
end
obj_to_xml(obj,xml) click to toggle source

This is called by the XML unmarshalling machinery when the state of an instance of this node's @owner is to be stored into an XML tree. obj is the instance, xml is the tree (a REXML::Element). The node must extract “its” data from obj and store it to the corresponding parts (sub-elements, attributes etc.) of xml (using XML::XXPath or any other means).

# File lib/xml/mapping/base.rb, line 607
def obj_to_xml(obj,xml)
  raise "abstract method called"
end
xml_to_obj(obj,xml) click to toggle source

This is called by the XML unmarshalling machinery when the state of an instance of this node's @owner is to be read from an XML tree. obj is the instance, xml is the tree (a REXML::Element). The node must read “its” data from xml (using XML::XXPath or any other means) and store it to the corresponding parts (attributes etc.) of obj's state.

# File lib/xml/mapping/base.rb, line 597
def xml_to_obj(obj,xml)
  raise "abstract method called"
end