class Cda::XmlParser
Attributes
registry[RW]
xml[R]
Public Class Methods
new(xml, registry)
click to toggle source
# File lib/cda/xml_parser.rb, line 6 def initialize(xml, registry) @registry = registry @xml = xml end
Public Instance Methods
parse(model_class = nil)
click to toggle source
# File lib/cda/xml_parser.rb, line 11 def parse(model_class = nil) instantiate_from_element(model_class || resolve_class) end
value_of(node_or_xpath, opts = {})
click to toggle source
# File lib/cda/xml_parser.rb, line 32 def value_of(node_or_xpath, opts = {}) if node_or_xpath.is_a?(String) node_set = xml.xpath(node_or_xpath) return if node_set.blank? if node_set.length > 1 raise "Expected only one node as result of #{node_or_xpath}, but #{node_set.inspect}" end node = node_set.first else node = node_or_xpath end case opts[:as] when :numeric parse_numeric(node) when :boolean parse_boolean(node) when :datetime, :date parse_time(node) when :coded_value parse_coded_value(node) when :time_interval parse_time_interval(node) when :value_with_unit parse_value_with_unit(node) else node.text if node.present? end end
values_of(xpath, opts = {})
click to toggle source
# File lib/cda/xml_parser.rb, line 62 def values_of(xpath, opts = {}) xml.xpath(xpath).map { |node| value_of(node, opts) } end
within(*args) { || ... }
click to toggle source
# File lib/cda/xml_parser.rb, line 22 def within(*args) xpath_or_node, xpath = args node = xpath_or_node.is_a?(String) ? xml.xpath(xpath_or_node) : xpath_or_node node = node.xpath(xpath) if xpath saved_node, @xml = @xml, node yield if @xml.present? ensure @xml = saved_node end
within_each(xpath_or_nodes, &block)
click to toggle source
# File lib/cda/xml_parser.rb, line 15 def within_each(xpath_or_nodes, &block) nodes = xpath_or_nodes.is_a?(String) ? xml.xpath(xpath_or_nodes) : xpath_or_nodes nodes.each do |node| within(node, &block) end end
Private Instance Methods
coerce_value(value, type)
click to toggle source
# File lib/cda/xml_parser.rb, line 109 def coerce_value(value, type) if type <= Date Cda::ValueCoercer.string_to_time(value) else value end end
instantiate_from_element(model_class)
click to toggle source
# File lib/cda/xml_parser.rb, line 121 def instantiate_from_element(model_class) meta_info = Cda::MetaInfo.for(model_class) instance = model_class.new parse_text(instance, meta_info.text) if meta_info.has_text? meta_info.attributes.each { |attr| parse_attribute(instance, attr) } meta_info.elements.each { |element| parse_element(instance, element) } instance end
parse_attribute(instance, attribute)
click to toggle source
# File lib/cda/xml_parser.rb, line 68 def parse_attribute(instance, attribute) value = value_of("@#{attribute.fully_qualified_name}") attribute.set_value(instance, coerce_value(value, attribute.model_class)) end
parse_element(instance, element)
click to toggle source
# File lib/cda/xml_parser.rb, line 73 def parse_element(instance, element) if element.collection? parse_elements_collection(instance, element) else parse_single_element(instance, element) end end
parse_elements_collection(instance, element)
click to toggle source
# File lib/cda/xml_parser.rb, line 89 def parse_elements_collection(instance, element) items = element.new_instance within_each [element.wrapper_element_name, element.element_name].compact.join('/') do items << parse_value(element) end element.set_value(instance, items) end
parse_single_element(instance, element)
click to toggle source
# File lib/cda/xml_parser.rb, line 81 def parse_single_element(instance, element) unwrap_node_if_required(element) do within element.element_name do element.set_value(instance, parse_value(element)) end end end
parse_text(instance, text_element)
click to toggle source
# File lib/cda/xml_parser.rb, line 117 def parse_text(instance, text_element) text_element.set_value(instance, values_of('text()').join) end
parse_value(element)
click to toggle source
# File lib/cda/xml_parser.rb, line 97 def parse_value(element) if (model_class = resolve_class) instantiate_from_element(model_class) elsif (type = value_of('@type')) instantiate_from_element("Cda::#{type}".constantize) elsif element.complex? instantiate_from_element(element.model_class) else coerce_value(value_of('text()'), element.model_class) end end
resolve_class()
click to toggle source
# File lib/cda/xml_parser.rb, line 130 def resolve_class template_id = value_of 'templateId/@root' template_id.presence && registry[template_id] end
unwrap_node_if_required(element) { || ... }
click to toggle source
# File lib/cda/xml_parser.rb, line 135 def unwrap_node_if_required(element) if element.wrapper_element_name within(element.wrapper_element_name) do yield end else yield end end