Class: XML::Mapping::Node

Inherits:
Object
  • Object
show all
Defined in:
lib/xml/mapping/base.rb

Overview

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.

Direct Known Subclasses

ChoiceNode, SingleAttributeNode

Instance Method Summary collapse

Constructor Details

#initialize(owner, *args) ⇒ Node

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.



550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
# 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

Instance Method Details

#is_present_in?(obj) ⇒ Boolean

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 ChoiceNode#obj_to_xml.

Returns:

  • (Boolean)


629
630
631
# File 'lib/xml/mapping/base.rb', line 629

def is_present_in? obj
  true
end

#obj_initializing(obj, mapping) ⇒ Object

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.



622
623
# File 'lib/xml/mapping/base.rb', line 622

def obj_initializing(obj,mapping)
end

#obj_to_xml(obj, xml) ⇒ Object

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).



607
608
609
# File 'lib/xml/mapping/base.rb', line 607

def obj_to_xml(obj,xml)
  raise "abstract method called"
end

#xml_to_obj(obj, xml) ⇒ Object

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.



597
598
599
# File 'lib/xml/mapping/base.rb', line 597

def xml_to_obj(obj,xml)
  raise "abstract method called"
end