Rails XML builder with no pretty-printing (i.e. minified XML)

一世执手 提交于 2019-12-07 15:52:16

问题


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:

  1. (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
    
  2. (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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!