2009-08-22 16 views
3

J'utilise Builder :: XmlMarkup pour produire des structures de données au format XML pour un serveur API RESTful.Générateur Rails XML sans impression (c'est-à-dire XML minifié)

Récemment, j'ai découvert un bogue où la jolie impression de Builder :: XmlMarkup produisait un élément plein de texte d'espaces au lieu d'un élément vide comme il se doit.

Par exemple, ce code:

xml.outertag do 
    xml.list do 
    # Some code which loops through a list 
    end 
end 

est produit:

<outertag> 
    <list> 
    </list> 
</outertag> 

Lorsque la liste intérieure est une liste vide, l'élément doit être vide —-à-dire < liste /> ou < liste > </list>. Cependant, le code XML réel est une balise liste> < remplie d'un saut de ligne et d'autres espaces. Alors, comment puis-je éliminer complètement la jolie impression de Builder? Actuellement, je pense à Builder :: XmlMarkup de correction de singe de sorte que initialize ignore les paramètres : indent; même si je considère un after_filter aussi.

Répondre

3

L'appel Builder::XmlMarkup.new sans aucun paramètre de retrait ne devrait pas vous donner d'espace.

xml = Builder::XmlMarkup.new 
xml.outertag do 
    xml.list do 
    # Some code which loops through a list 
    end 
end 

xml # => <outertag><list></list></outertag> 
0

Accepter la réponse de Matt car elle semble la plus généralement applicable. Cependant depuis que ma situation est une API qui produit XML pour chaque URL, je veux quelque chose qui fonctionne à travers le conseil.

Voici deux solutions pour que:

  1. (Ma solution actuelle) Faire un plugin simple qui ActionView singe-patches :: TemplateHandlers :: Builder pour forcer 0 indentation (selon la réponse de Matt). Malheureusement, ActionView :: TemplateHandlers :: Builder est principalement une chaîne opaque de code Ruby qui est eval() ed plus tard. Voici mon module principal, que je comprends dans: (. Probablement une solution future)

    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. Il me semble qu'un service Web XML sérieux a besoin pour traiter XML entrant et sortant, pour valider et faire tout ce qui est nécessaire. C'est un bon candidat pour le middleware Rack. Je prévois donc éventuellement d'écrire une simple couche middleware Rack qui va valider le XML sortant (sonner l'alarme si elle est invalide, etc.) et ensuite soit l'imprimer en mode développement, soit la compacter en production.