Constructor Rails XML sin impresión bonita (es decir,XML minimizado)
-
19-09-2019 - |
Pregunta
Estoy usando Builder::XmlMarkup para producir estructuras de datos en formato XML para un servidor API RESTful.
Recientemente, descubrí un error en el que la impresión bonita de Builder::XmlMarkup producía un elemento lleno de texto con espacios en blanco en lugar de un elemento vacío como debería.
Por ejemplo, este código:
xml.outertag do
xml.list do
# Some code which loops through a list
end
end
está produciendo:
<outertag>
<list>
</list>
</outertag>
Cuando la lista interna es una lista vacía, el elemento debe estar vacío, es decir.<lista/> o <lista></lista>.Sin embargo, el XML real es una etiqueta <list> rellena con una nueva línea y otros espacios en blanco.
Entonces, ¿cómo puedo eliminar por completo la impresión bonita de Builder?Actualmente, estoy pensando en parchear Builder::XmlMarkup para que la inicialización ignore el :sangrar parámetros;aunque también estoy considerando un after_filter.
Solución
Llamando Builder::XmlMarkup.new
sin ningún parámetro de guión en absoluto no debe darle ningún espacio en blanco.
xml = Builder::XmlMarkup.new
xml.outertag do
xml.list do
# Some code which loops through a list
end
end
xml # => <outertag><list></list></outertag>
Otros consejos
Aceptar la respuesta de Matt porque parece la más aplicable en general.Sin embargo, dado que mi situación es una API que genera XML para cada URL, quiero algo que funcione en todos los ámbitos.
Aquí hay dos soluciones para eso:
(Mi solución actual) Cree un complemento simple que parchee ActionView::TemplateHandlers::Builder para forzar la sangría 0 (según la respuesta de Matt).Desafortunadamente, ActionView::TemplateHandlers::Builder es principalmente una cadena opaca de código Ruby que se evalúa() más adelante.Aquí está mi módulo principal, que incluyo en:
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
(Probablemente una solución futura). Se me ocurre que un servicio web serio basado en XML necesita procesar XML entrante y saliente, validarlo y hacer todo lo demás que sea necesario.Es un buen candidato para el middleware Rack.Entonces, eventualmente me preveo escribiendo una capa de middleware Rack simple que validará el XML saliente (haciendo sonar la alarma si no es válido, etc.) y luego lo imprimirá si está en modo de desarrollo o lo compactará en producción.