lib/csl/node.rb in csl-1.0.0.pre10 vs lib/csl/node.rb in csl-1.0.0.pre11

- old
+ new

@@ -64,34 +64,49 @@ else default_attributes.merge(attributes) end end + def parse(data) + parse!(data) + rescue + nil + end + + def parse!(data) + node = CSL.parse!(data, self) + + raise ParseError, "root node not #{self.name}: #{node.inspect}" unless + node.class == self || Node.equal?(self) + + node + end + private - def has_language - attr_accessor :language - - define_method :has_language? do - !language.nil? - end - - public :language, :language=, :has_language? - - alias_method :original_attribute_assignments, :attribute_assignments - - define_method :attribute_assignments do - if has_language? - original_attribute_assignments.unshift('xml:lang="%s"' % language) - else - original_attribute_assignments - end - end - - private :original_attribute_assignments, :attribute_assignments - end + def has_language + attr_accessor :language + define_method :has_language? do + !language.nil? + end + + public :language, :language=, :has_language? + + alias_method :original_attribute_assignments, :attribute_assignments + + define_method :attribute_assignments do + if has_language? + original_attribute_assignments.unshift('xml:lang="%s"' % language) + else + original_attribute_assignments + end + end + + private :original_attribute_assignments, :attribute_assignments + end + def attr_defaults(attributes) @default_attributes = attributes end # Creates a new Struct for the passed-in attributes. Node instances @@ -118,17 +133,21 @@ # of the attribute variables. def keys __class__.keys end + def symbolize_keys + self + end + def values super.compact end - # def to_a - # keys.zip(values_at(*keys)).reject { |k,v| v.nil? } - # end + def to_hash + Hash[keys.zip(values_at(*keys)).reject { |_, v| v.nil? }] + end # @return [Boolean] true if all the attribute values are nil; # false otherwise. def empty? values.compact.empty? @@ -190,10 +209,27 @@ @children = self.class.create_children yield self if block_given? end + def initialize_copy(other) + super + @attributes = self.class.create_attributes(other.attributes) + @children = self.class.create_children + @parent, @ancestors, @descendants, @siblings, @root, @depth = nil + end + + def deep_copy + copy = dup + + each_child do |child| + copy.add_child child.deep_copy + end + + copy + end + # Iterates through the Node's attributes def each if block_given? attributes.each_pair(&Proc.new) self @@ -213,13 +249,13 @@ # false otherwise. def has_attributes? !attributes.empty? end - def has_language? - false - end + def has_language? + false + end def textnode? false end alias has_text? textnode? @@ -249,12 +285,17 @@ # no other attributes than specified by the conditions, {#exact_match?} # should be used instead. # # @see #exact_match? # - # If the optional - # @param name [String,Regexp] must match the nodename + # @example + # node.match?(name, conditions) + # node.match?(conditions) + # node.match?(other_node) + # + # @param name [String,Regexp,Node] must match the nodename; alternatively + # you can pass a node # @param conditions [Hash] the conditions # # @return [Boolean] whether or not the query matches the node def match?(name = nodename, conditions = {}) name, conditions = match_conditions_for(name, conditions) @@ -284,11 +325,17 @@ # Note that all node attributes are used by this method – if you want # to match only a subset of attributes {#match?} should be used instead. # # @see #match? # - # @param name [String,Regexp] must match the nodename + # @example + # node.exact_match?(name, conditions) + # node.exact_match?(conditions) + # node.exact_match?(other_node) + # + # @param name [String,Regexp,Node] must match the nodename; alternatively + # you can pass a node # @param conditions [Hash] the conditions # # @return [Boolean] whether or not the query matches the node exactly def exact_match?(name = nodename, conditions = {}) name, conditions = match_conditions_for(name, conditions) @@ -301,24 +348,24 @@ condition === value end end alias matches_exactly? exact_match? - # @option filter [Array] a list of attribute names - # @return [Hash] the node's attributes matching the filter - def attributes_for(*filter) - filter.flatten! + # @option filter [Array] a list of attribute names + # @return [Hash] the node's attributes matching the filter + def attributes_for(*filter) + filter.flatten! - Hash[map { |name, value| - !value.nil? && filter.include?(name) ? [name, value.to_s] : nil - }.compact] - end + Hash[map { |name, value| + !value.nil? && filter.include?(name) ? [name, value.to_s] : nil + }.compact] + end - # @return [Hash] the node's formatting options - def formatting_options - attributes_for Schema.attr(:formatting) - end + # @return [Hash] the node's formatting options + def formatting_options + attributes_for Schema.attr(:formatting) + end def <=>(other) [nodename, attributes, children] <=> [other.nodename, other.attributes, other.children] rescue nil @@ -347,19 +394,26 @@ end alias to_s pretty_print + protected + + def match_conditions + end + private def attribute_assignments each_pair.map { |name, value| value.nil? ? nil : [name, value.to_s.inspect].join('=') }.compact end def match_conditions_for(name, conditions) case name + when Node + [name.nodename, name.attributes.to_hash] when Hash conditions, name = name, nodename when Symbol name = name.to_s end \ No newline at end of file