Экстра <to_s/"> при использовании построителя для генерации XML

Я пытаюсь создать KML с помощью Builder. Я знаю, что у них есть некоторые варианты, чтобы помочь с этим, но я буду делать некоторые 2.2 специфические вещи, которые не поддерживаются камнями KML, на которые я смотрел, и, как правило, хотел бы сделать это, используя только XML-структуру.

Я получаю тег в конце файла при рендеринге моего kml/xml. Я сильно подозреваю, что мне не хватает чего-то основного с настройкой моего объекта Builder или с тем, как я его выводю. Вот простой пример, демонстрирующий проблему:

def kml2dot2
  @site = Site.find(params[:id])
  xml = Builder::XmlMarkup.new(:indent => 2)
  xml.instruct!
  xml.kml("xmlns" => "http://www.opengis.net/kml/2.2") {
    xml.Placemark do
      xml.name @site.mapNameFull
      xml.Point do
        xml.coordinates @site.lat.to_s + "," + @site.lng.to_s + ",0"
      end
    end
  }
  render :text => xml, :type=>"text/kml"

end 

Выдает:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Placemark>
    <name>Seattle City Hall</name>
    <Point>
      <coordinates>47.6040746,-122.33005,0</coordinates>
    </Point>
  </Placemark>
</kml>
<to_s/>

Я пытаюсь понять, как избежать включения <to_s/> и того, что я делаю неправильно с Builder. Спасибо за понимание.

Ответ 1

Вам не нужно инициализировать объект построителя XML. Просто используйте обработчик шаблона встроенного построителя.

  • Вызвать шаблон kml2dot2.xml.builder
  • Напишите код непосредственно в представлении

Пример

def kml2dot2
  @site = Site.find(params[:id])
end

# kml2dot2.xml.builder
xml.kml("xmlns" => "http:// www.opengis.net/kml/2.2") do
  xml.Placemark do
    xml.name @site.mapNameFull
    xml.Point do
       xml.coordinates "#{@site.lat},#{@site.lng},0"
    end
  end
end

Ответ 2

Мой короткий исходный ответ

Чтобы получить фактическое содержимое строки Builder, вам нужно вызвать метод target!

xml = Builder.new
# do your stuff...
xml.target! #returns the string
#where as calling most other methods (like to_s) to the builder object will just
#generate an element tag by that method name.


И затем немного более подробное объяснение того, что и почему происходит в случае OPs

Когда вы передаете объект-конструктор xml в метод рендеринга, Rails автоматически вызовет для него метод to_s. Обычно это означает, что вам не нужно беспокоиться о типе данных, которые вы передаете для средства визуализации, так как в любом случае он будет преобразован в String. Очень удобно! Однако с объектом Builder вам нужно сделать преобразование самостоятельно, так как строитель предполагает, что любое отправленное ему сообщение - это запрос на добавление нового элемента по имени. Поэтому вызов xml.to_s ведет себя так же, как вызов xml.kml, добавляет новый элемент. В этом случае вы не называете to_s своим "я", поэтому это не так очевидно и легко пропустить. Простым решением для этого является вызов render следующим образом:

render :text => xml.target!, :type=>"text/kml"