lib/happymapper.rb in happymapper-0.1.7 vs lib/happymapper.rb in happymapper-0.2.0
- old
+ new
@@ -23,22 +23,22 @@
module ClassMethods
def attribute(name, type, options={})
attribute = Attribute.new(name, type, options)
@attributes[to_s] ||= []
@attributes[to_s] << attribute
- create_accessor(attribute.name)
+ attr_accessor attribute.method_name.intern
end
def attributes
@attributes[to_s] || []
end
def element(name, type, options={})
element = Element.new(name, type, options)
@elements[to_s] ||= []
@elements[to_s] << element
- create_accessor(element.name)
+ attr_accessor element.method_name.intern
end
def elements
@elements[to_s] || []
end
@@ -49,93 +49,73 @@
def has_many(name, type, options={})
element name, type, {:single => false}.merge(options)
end
- def tag(new_tag_name)
+ # Options:
+ # :root => Boolean, true means this is xml root
+ def tag(new_tag_name, o={})
+ options = {:root => false}.merge(o)
+ @root = options.delete(:root)
@tag_name = new_tag_name.to_s
end
def get_tag_name
- @tag_name ||= to_s.downcase
+ @tag_name ||= begin
+ to_s.split('::')[-1].downcase
+ end
end
+
+ def is_root?
+ @root
+ end
- def parse(xml, o={})
- options = {
- :single => false,
- :use_default_namespace => false,
- }.merge(o)
+ def parse(xml, o={})
+ xpath, collection, options = '', [], {:single => false}.merge(o)
+ doc = xml.is_a?(LibXML::XML::Node) ? xml : xml.to_libxml_doc
+ node = doc.respond_to?(:root) ? doc.root : doc
- namespace = "default_ns:" if options[:use_default_namespace]
- doc = xml.is_a?(LibXML::XML::Node) ? xml : xml.to_libxml_doc
+ # puts doc.inspect, doc.respond_to?(:root) ? doc.root.inspect : ''
- nodes = if namespace
- node = doc.respond_to?(:root) ? doc.root : doc
- node.register_default_namespace(namespace.chop)
- node.find("#{namespace}#{get_tag_name}")
- else
- doc.find("//#{get_tag_name}")
+ unless node.namespaces.default.nil?
+ namespace = "default_ns:"
+ node.namespaces.default_prefix = namespace.chop
+ # warn "Default XML namespace present -- results are unpredictable"
end
-
- nodes = if namespace
- node = doc.respond_to?(:root) ? doc.root : doc
- node.register_default_namespace(namespace.chop)
- node.find("#{namespace}#{get_tag_name}")
- else
- nested = '.' unless doc.respond_to?(:root)
- path = "#{nested}//#{get_tag_name}"
- doc.find(path)
+
+ if node.namespaces.to_a.size > 0 && namespace.nil? && !node.namespaces.namespace.nil?
+ namespace = node.namespaces.namespace.prefix + ":"
end
-
- collection = create_collection(nodes, namespace)
- # per http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/Document.html#M000354
- nodes = nil
- GC.start
+ # xpath += doc.respond_to?(:root) ? '' : '.'
+ xpath += is_root? ? '/' : './/'
+ xpath += namespace if namespace
+ xpath += get_tag_name
+ # puts "parse: #{xpath}"
- options[:single] ? collection.first : collection
- end
-
- private
- def create_collection(nodes, namespace=nil)
- nodes.inject([]) do |acc, el|
- obj = new
- attributes.each { |attr| obj.send("#{normalize_name attr.name}=", attr.from_xml_node(el)) }
- elements.each { |elem| obj.send("#{normalize_name elem.name}=", elem.from_xml_node(el, namespace)) }
- acc << obj
+ nodes = node.find(xpath)
+ nodes.each do |n|
+ obj = new
+
+ attributes.each do |attr|
+ obj.send("#{attr.method_name}=",
+ attr.from_xml_node(n))
end
+
+ elements.each do |elem|
+ elem.namespace = namespace
+ obj.send("#{elem.method_name}=",
+ elem.from_xml_node(n))
+ end
+ collection << obj
end
-
- def create_getter(name)
- name = normalize_name(name)
- class_eval <<-EOS, __FILE__, __LINE__
- def #{name}
- @#{name}
- end
- EOS
- end
+ # per http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/Document.html#M000354
+ nodes = nil
+ GC.start
- def create_setter(name)
- name = normalize_name(name)
-
- class_eval <<-EOS, __FILE__, __LINE__
- def #{name}=(value)
- @#{name} = value
- end
- EOS
- end
-
- def create_accessor(name)
- name = normalize_name(name)
-
- create_getter(name)
- create_setter(name)
- end
-
- def normalize_name(name)
- name.gsub('-', '_')
- end
+ options[:single] || is_root? ? collection.first : collection
+ end
end
end
require 'happymapper/item'
require 'happymapper/attribute'