2017-07-16 2 views
0

J'essaye de compacter un XML existant en utilisant Nokogiri. J'ai le code de démonstration suivante:Compacter XML existant en utilisant nokogiri

#!/usr/bin/env ruby 
require 'nokogiri' 

doc = Nokogiri.XML <<-XML.strip 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <foo> 
    <bar>test</bar> 
    </foo> 
</root> 
XML 

doc.write_xml_to($stdout, indent: 0) 

Je me attendais à voir

<?xml version="1.0" encoding="UTF-8"?> 
<root><foo><bar>test</bar></foo></root> 

Mais au lieu que j'ai vu

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <foo> 
    <bar>test</bar> 
    </foo> 
</root> 

J'ai essayé

doc.write_to($stdout, indent: 0, save_with: Nokogiri::XML::Node::SaveOptions::AS_XML) 

mais n » Je ne travaille pas non plus.

Comment puis-je supprimer les espaces ignorables?

+0

https://stackoverflow.com/questions/8406251/nokogiri-to-xml-without-carriage-returns peut Aidez-moi. J'allais suggérer des sous mais ce n'est pas faisable si vous avez plusieurs niveaux de données. Le seul autre que je peux penser est d'utiliser regex, mais si vous aviez des chaînes longues dans les attributs ou les valeurs XML alors cela ne fonctionnerait probablement pas non plus. – whodini9

+1

@ whodini9 Je n'utilise pas de constructeur car mon but ultime est de compacter un fichier XML existant. De plus, selon la documentation officielle et le code source de Nokogiri, 'Node # write_xml_to' appelle simplement' Node # write_to' avec l'option 'save_with: DEFAULT_XML'. Au fait, 'AS_XML' est un alias de' DEFAULT_XML'. –

Répondre

0

D'accord, je réponds à ma propre question. Nokogiri ne supprime pas les espaces blancs car Nokogiri ne sait pas si les espaces blancs sont ignorables ou non (pas de DTD, pas de schéma), donc il conserve tout le texte en tant qu'espace. Je devrais les supprimer manuellement avant d'écrire le document XML sur le périphérique IO.

#!/usr/bin/env ruby 
require 'bundler' 
Bundler.require :default 

doc = Nokogiri.XML <<-XML.strip 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <foo> 
    <bar>test</bar> 
    </foo> 
</root> 
XML 

# remove ignorable white spaces 
doc.xpath('//text()').each do |node| 
    node.content = '' if node.text =~ /\A\s+\z/m 
end 

doc.write_xml_to($stdout, indent: 0) 

Ceci est un grand progrès pour moi, mais je n'ai toujours pas atteint mon objectif parce que le fichier XML je travaille a des étiquettes auto-fermeture inline, et il y a des noeuds de texte contenant des espaces uniquement entre les les étiquettes qui ne devraient pas être compactées. J'essaie de trouver un moyen de gérer ce cas de coin maintenant.

0

Vous pouvez dire Nokogiri ignorer les nœuds de texte vides, puis à la sortie sans indentation:

require 'nokogiri' 

xml = <<EOT 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <foo> 
    <bar>test</bar> 
    </foo> 
</root> 
EOT 

doc = Nokogiri::XML(xml) { |opts| 
    opts.noblanks 
    opts.strict.noblanks 
} 
doc.to_xml(:indent_text => '', :indent => 0) 
# => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
# "<root>\n" + 
# "<foo>\n" + 
# "<bar>test</bar>\n" + 
# "</foo>\n" + 
# "</root>\n"