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.

¿Fue útil?

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:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top