require "relaton" require "relaton_iev/version" require "htmlentities" module RelatonIev class Error < StandardError; end class << self IEVPATH = <<~IEV.strip.freeze //*[@citeas = 'IEC 60050:2011' or @citeas = 'IECĀ 60050:2011' or @citeas = 'IEC 60050:2011' or @citeas = 'IEC 60050:2011'] IEV # converts generic IEV citation to citation of IEC 60050-n # assumes IEV citations are of form # # 101-01-01 # # # @param xmldoc [Nokogiri::XML::Documet] # @return [Set] def links_iev2iec60050part(xmldoc) parts = Set.new xmldoc.xpath(IEVPATH).each do |x| m = x.at(".//locality[@type = 'clause']/referenceFrom")&.text &.sub(/^(\d+).*$/, "\\1") or next parts << m x["citeas"] = @c.decode(x["citeas"]).sub(/60050/, "60050-#{m}") x["bibitemid"] = "IEC60050-#{m}" end parts end # replace generic IEV reference with references to all extracted # IEV parts # # @param xml [Nokogiri::XML::Document] # @param parts [Set] # @param iev [Nokogiri::XML::Element] # @param bibdb [Relaton::Db, NilClass] # @return [Nokogiri::XML::Element] def refs_iev2iec60050part(xml, parts, bibdb = nil) bibdb or return "" new_iev = "" parts.sort.each do |p| hit = get_iev_part(bibdb, p) or next new_iev += refs_iev2iec60050part1(xml, p, hit) update_iev_refs(xml, p, hit) end new_iev end def get_iev_part(bibdb, part) unless hit = bibdb.fetch("IEC 60050-#{part}", nil, keep_year: true) @err << "The IEV document 60050-#{part} that has been cited " \ "does not exist" end hit end def update_iev_refs(xml, part, hit) xml.xpath(IEVPATH.gsub(/60050/, "60050-#{part}")).each do |x| x["citeas"] = @c.decode(x["citeas"]) .sub(/:2011$/, ":#{hit.date[0].on(:year)}") end end def refs_iev2iec60050part1(xmldoc, part, hit) date = hit.date[0].on(:year) return "" if already_contains_ref(xmldoc, part, date) id = xmldoc.at("//bibitem[@id = 'IEC60050-#{part}']") ? "-1" : "" hit.to_xml.sub(/ id="[^"]+"/, %{ id="IEC60050-#{part}#{id}"}) end def already_contains_ref(xmldoc, part, date) xmldoc.at("//bibliography//bibitem[not(ancestor::bibitem)]/" \ "docidentifier[@type = 'IEC']" \ "[text() = 'IEC 60050-#{part}:#{date}']") end # @param xmldoc [Nokogiri::XML::Document] # @param bibdb [Relaton::Db, NilClass] # @return [Nokogiri::XML::Element], [String] def iev_cleanup(xmldoc, bibdb = nil) @c = HTMLEntities.new @err = [] iev = xmldoc.at("//bibitem[docidentifier = 'IEC 60050:2011']") or return [nil, @err] parts = links_iev2iec60050part(xmldoc) [iev.replace(refs_iev2iec60050part(xmldoc, parts, bibdb)), @err] end end end