问题
I am using Builder::XmlMarkup to produce data structures in XML format for a RESTful API server.
Recently, I discovered a bug where the pretty-printing from Builder::XmlMarkup produced an element full of whitespace text instead of an empty element as it should.
For example, this code:
xml.outertag do
xml.list do
# Some code which loops through a list
end
end
is producing:
<outertag>
<list>
</list>
</outertag>
When the inner list is an empty list, the element must be empty—i.e. <list/> or <list></list>. However the actual XML is a <list> tag filled with a newline and other whitespace.
So, how can I eliminate Builder pretty-printing altogether? Currently, I am thinking of monkey-patching Builder::XmlMarkup so that initialize ignores the :indent parameters; although I'm considering an after_filter as well.
回答1:
Calling Builder::XmlMarkup.new
without any indent parameter at all shouldn’t give you any whitespace.
xml = Builder::XmlMarkup.new
xml.outertag do
xml.list do
# Some code which loops through a list
end
end
xml # => <outertag><list></list></outertag>
回答2:
Accepting Matt's answer as it seems the most generally-applicable. However since my situation is an API that outputs XML for every URL, I want something that works across the board.
Here are two solutions for that:
(My current solution) Make a simple plugin that monkey-patches ActionView::TemplateHandlers::Builder to force 0 indentation (as per Matt's answer). Unfortunately, ActionView::TemplateHandlers::Builder is mostly an opaque string of Ruby code that is eval()ed later. Here is my main module, which I include in:
module MinimalXml module Builder def self.included(base) base.class_eval do def compile(template) indent = 0 "_set_controller_content_type(Mime::XML);" + "xml = ::Builder::XmlMarkup.new(:indent => #{indent});" + "self.output_buffer = xml.target!;" + template.source + ";xml.target!;" end end end end end
(Probably a future solution.) It occurs to me that a serious XML-based web service needs to process incoming and outgoing XML, to validate it and do whatever else is necessary. That is a good candidate for Rack middleware. So eventually I foresee myself writing a simple Rack middleware layer which will validate the outgoing XML (sounding the alarm if it is invalid, etc.) and then either pretty-print it if in development mode, or compactify it in production.
来源:https://stackoverflow.com/questions/1316020/rails-xml-builder-with-no-pretty-printing-i-e-minified-xml