Para formatear ficheros XML generalmente uso la variante 3 descrita en Formatear ficheros XML pero recientemente he tenido la necesidad de trabajar con ficheros XML que además de estar ofuscado una parte del XML usa entidades html, partamos de que debemos trabajar con un fichero XML como el siguiente:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE Edit_Mensaje SYSTEM "Edit_Mensaje.dtd">
<Edit_Mensaje>
<Mensaje>
<Remitente>
<Nombre>Nombre del remitente</Nombre>
<Mail> Correo del remitente </Mail>
</Remitente>
<Destinatario>
<Nombre>Nombre del destinatario</Nombre>
<Mail>Correo del destinatario</Mail>
</Destinatario>
<Texto>
<Asunto>
Este es mi documento con una estructura muy sencilla
no contiene atributos ni entidades...
</Asunto>
<Parrafo>
Este es mi documento con una estructura muy sencilla
no contiene atributos ni entidades...
</Parrafo>
</Texto>
</Mensaje>
</Edit_Mensaje>
Nota: Fichero Obtenido de Wikipedia: Extensible Markup Language
pero que en lugar de tenerlo como se muestra más arriba lo tenemos de la siguiente manera:
<Edit_Mensaje><Mensaje><Remitente><Nombre>Nombre del remitente</Nombre><Mail>Correo del remitente</Mail></Remitente><Destinatario><Nombre>Nombre del destinatario</Nombre><Mail>Correo del destinatario</Mail></Destinatario><Texto><Asunto>Este es mi documento con una estructura muy sencilla no contiene atributos ni entidades...</Asunto><Parrafo>Este es mi documento con una estructura muy sencilla no contiene atributos ni entidades... </Parrafo></Texto></Mensaje></Edit_Mensaje>
¿No muy bonito verdad? y no podemos aplicar las soluciones ofrecidas en Formatear ficheros XML debido a que el XML contiene entidades html así que tuve echarle mano y hacer un script primero en Python y luego en PHP:
Scripts
Ambos script ejecutan la siguiente lógica:
- Lee el nombre del fichero de la entrada standard
- Comprueba que el fichero existe y que el mismo se puede leer
- Almacena el contenido del fichero en una variable
- Decodifica entidades html
- Formatea el XML
- Visualiza el XML en un formato entendible
Script en Python
#!/usr/bin/python import os import re import HTMLParser as parser import xml.dom.minidom as minidom import sys try: # Read de file name from standard input filename = sys.argv[1] if os.path.isfile(filename) and os.access(filename, os.R_OK): # Open the file in read only mode file = open(filename, 'r') # Read the file and decode html entities xml = parser.HTMLParser().unescape(file.read()) # Pretify the xml xml = minidom.parseString(xml).toprettyxml() # Handle issue with CDATA section due minidom add extraspace # before/after CDATA xml = re.sub('>\s+<!', '><!', xml) xml = re.sub(']>\s+<', ']><', xml) # Remove empty lines # Thanks to http://stackoverflow.com/questions/1140958/whats-a-quick-one-liner-to-remove-empty-lines-from-a-python-string print "".join([s for s in xml.strip().splitlines(True) if s.strip()]) else: print "File is missing or is not readable!" except IndexError: print "You must specify a file name!"
Script en PHP
#!/usr/bin/env php <?php // Check the scripts is called with arguments if (empty($argv[1])) { die('You must specify a file!'); } // Set the file name $file = $argv[1]; // Verify if filename exists if (!is_readable($file)) { die('File is missing or is not readable!'); } // Get the file content $content = file_get_contents($file); // Verify the content is not empty if (empty($content)) { die('File is empty nothing to do ;)'); } // Decode html entities $content = html_entity_decode($content); // Parse the xml and format it $doc = new DOMDocument(); $doc->preserveWhiteSpace = false; $doc->formatOutput = true; $doc->loadXML($content); // Print the result echo $doc->saveXML();
Ahora podemos integrar los scripts anteriores con gedit para ello (En este caso solo lo haremos para el script desarrollado en PHP):
- Ejecutamos gedit
- Menu > Tools > Manage External Tool
- Agregamos una nueva herramienta externa y establecemos los valores como muestra la figura
Abrimos nuestro fichero xml al cual le llamamos garbage.xml
Luego lo formateamos usando la combinación de teclas que establecimos cuando integramos la herramientas externa en el gedit y nos quedaría como muestra la figura.
Excelente post, estoy usando el script en python con unas pequeñas modificaciones para hacerlo funcionar como acción personalizada en thunar, además de un port a python3.
El repo github donde lo tengo alojado es en:
https://github.com/danesc87/dotsAndConfs
Gracias por tu contribución y hace un port a python3, los scripts anteriores también se pueden encontrar en:
Python: https://gist.github.com/yoander/ae488ac7465a9e77f6f63b0c61e58f5c
PHP: https://gist.github.com/yoander/7b9821ad5d077dc88cc29e1ab031ea0f
Ambos script pueden usarse, distribuirse y modificarse libremente ya que son liberados bajos licencia GPLv2+