I'm trying to generate KML using Builder. I know their are some options out there to help with this but I will be doing some 2.2 specific things that aren't supported by the KML gems I've looked at and would generally like to be able to accomplish this leveraging just an XML framework.
I get a tag at the end of the file when rendering my kml/xml. I strongly suspect I'm missing something basic with setting up my Builder object or with how I'm rendering the output it. Here's a simple example that demonstrates the issue:
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
Produces:
<?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/>
I'm trying to understand how to avoid the <to_s/>
being included and what I'm doing wrong with Builder. Thanks for any insight.
To get the actual string contents of the Builder you need to call the method 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.
When you pass the xml
builder object to the render method Rails will automatically call the to_s
method for it. Usually this means that you do not need to worry about the type of data that you pass for the renderer, since it will be converted to a String anyway. Very convenient! However, with the Builder object you need to do the conversion your self since the builder assumes that any message sent to it is a request to add a new element by the name. So calling xml.to_s
behaves just the same as calling xml.kml
, adds a new element. In this case your not calling to_s
your self so it is not so apparent and is easy to miss. The simple fix to this is to call render
like this:
render :text => xml.target!, :type=>"text/kml"
You don't need to initialize an XML builder object. Just use the integrated builder template handler.
Example
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With