module Mabmapper module MabXml module QueryHelper def field(name_or_enum, options={}) if name_or_enum.is_a?(String) query.add_field(name_or_enum, options) elsif name_or_enum.is_a?(Enumerable) name_or_enum.inject(query) { |q, name| q.add_field(name, options) } end end def subfield(name_or_enum) if name_or_enum.is_a?(String) query.add_subfield(name_or_enum) elsif name_or_enum.is_a?(Enumerable) name_or_enum.inject(query) { |q, name| q.add_subfield(name) } end end def get results = ResultSet.new query.xml.xpath(fields_xpath).each do |field_xml| name = field_xml.attribute('tag').to_s field = Field.new(name) field_xml.xpath(subfields_xpath).each do |subfield_xml| name = subfield_xml.attribute('code').to_s value = subfield_xml.text.presence subfield = Subfield.new(name, value) field.add_subfield(subfield) end results.add_field(field) end results end private def query self.is_a?(Query) ? self : Query.new(@xml) end def fields_xpath options = query.fields.map do |f| name = f[:name] ind1 = indicator_xpath("ind1", f[:options][:ind1]) ind2 = indicator_xpath("ind2", f[:options][:ind2]) s = [] s << "@tag='#{name}'" s << ind1 if ind1 s << ind2 if ind2 "(#{s.join(' and ')})" end.join(' or ') "/OAI-PMH/ListRecords/record/metadata/record/datafield[#{options}]" end def subfields_xpath global_negation = false options = query.subfields.map do |f| name = f[:name] negation = name.starts_with?('-') and name.length > 1 name = negation ? name.slice(1..-1) : name global_negation = true if negation negation ? "not(@code='#{name}')" : "@code='#{name}'" end options = global_negation ? options.join(' and ') : options.join(' or ') options.present? ? "subfield[#{options}]" : "subfield" end def indicator_xpath(name, value) global_negation = false options = [*value].map do |value| if value negation = value.starts_with?('-') and value.length > 1 global_negation = true if negation negation ? "not(@#{name}='#{value.slice(1..-1)}')" : "@#{name}='#{value}'" end end options = global_negation ? options.join(' and ') : options.join(' or ') options.present? ? "(#{options})" : nil end end end end