# frozen_string_literal: true class Map::KmlEditService def initialize(raw_kml) @raw_kml = raw_kml adjust_invalid_kml! end # add extended data do KML # Based on https://developers.google.com/kml/documentation/extendeddata def add_definition_custom_field(name, type) schema = Nokogiri::XML::Node.new('Schema', nokogiri) schema['name'] = name schema['id'] = "#{name}Id" simple_field = Nokogiri::XML::Node.new('SimpleField', nokogiri) simple_field['type'] = type simple_field['name'] = name schema << simple_field document << schema self end # Add new point to KML (Placemark) def add_point(lat, lon, data = {}) index = document.css('Placemark').length + 1 placemark = Nokogiri::XML::Node.new('Placemark', nokogiri) name = Nokogiri::XML::Node.new('name', nokogiri) name.content = "Point #{index}" # ExtendedData data.each do |key, value| add_extended_data(key, value, placemark) end # Point point = Nokogiri::XML::Node.new('Point', nokogiri) coordinates = Nokogiri::XML::Node.new('coordinates', nokogiri) coordinates.content = "#{lon},#{lat}" point << coordinates placemark << name placemark << point document_or_folder << placemark self end def add_default_value_to_placemarks(data) data.each do |name, value| check_definition!(name) document.css('Placemark').each do |placemark| add_extended_data(name, value, placemark) end end self end def to_xml nokogiri.to_xml end def remove_node(name) document.css(name.to_s).each(&:remove) self end private def nokogiri @nokogiri ||= Nokogiri::XML(@raw_kml) end def document @document ||= nokogiri.at_css('Document') end def document_or_folder @folder ||= nokogiri.at_css('Folder') || document end def check_definition!(name) has_definition = document.css("Schema SimpleField[name=#{name}]").any? raise "#{name} is not defined" unless has_definition end def add_extended_data(name, value, node) check_definition!(name) extendedData = Nokogiri::XML::Node.new('ExtendedData', nokogiri) schemaData = Nokogiri::XML::Node.new('SchemaData', nokogiri) schemaData['schemaUrl'] = "##{name}Id" extendedData << schemaData simpleData = Nokogiri::XML::Node.new('SimpleData', nokogiri) simpleData['name'] = name simpleData.content = value schemaData << simpleData node << extendedData end def adjust_invalid_kml! # Existem alguns KMLs (inválidos) que o nodo root é KML e não existe um document dentro # Nestes casos é necessário trocar o KML por Document unless nokogiri.at_css('Document') @raw_kml = @raw_kml.gsub('