使用构建器生成XML时的额外<to_s />

Nic*_*ick 11 xml ruby-on-rails builder kml

我正在尝试使用Builder生成KML.我知道他们有一些选择可以帮助解决这个问题,但是我会做一些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 
Run Code Online (Sandbox Code Playgroud)

生产:

<?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/>
Run Code Online (Sandbox Code Playgroud)

我试图了解如何避免<to_s/>被包含在内以及我在使用Builder时遇到的问题.感谢您的任何见解.

Tim*_*imo 16

我简短的原始答案

要获取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.
Run Code Online (Sandbox Code Playgroud)


然后对OPs案例中的内容和原因进行更详细的解释

xml构建器对象传递给render方法时,Rails将自动to_s为其调用方法.通常,这意味着您无需担心为渲染器传递的数据类型,因为无论如何它都将转换为String.很方便!但是,使用Builder对象时,您需要自行进行转换,因为构建器假定发送给它的任何消息都是通过名称添加新元素的请求.所以调用xml.to_s行为和调用一样xml.kml,添加一个新元素.在这种情况下,你不要打电话to_s给自己,所以它不是那么明显,很容易错过.对此的简单修复是这样调用render:

render :text => xml.target!, :type=>"text/kml"
Run Code Online (Sandbox Code Playgroud)


Sim*_*tti 1

您不需要初始化 XML 构建器对象。只需使用集成的构建器模板处理程序即可。

  1. 调用模板kml2dot2.xml.builder
  2. 直接在视图中编写代码

例子

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
Run Code Online (Sandbox Code Playgroud)