Formatear XML usando Python o PHP

Español English

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>&lt;Remitente&gt;&lt;Nombre&gt;Nombre del remitente&lt;/Nombre&gt;&lt;Mail&gt;Correo del remitente&lt;/Mail&gt;&lt;/Remitente&gt;&lt;Destinatario&gt;&lt;Nombre&gt;Nombre del destinatario&lt;/Nombre&gt;&lt;Mail&gt;Correo del destinatario&lt;/Mail&gt;&lt;/Destinatario&gt;&lt;Texto&gt;&lt;Asunto&gt;Este es mi documento con una estructura muy sencilla no contiene atributos ni entidades...&lt;/Asunto&gt;&lt;Parrafo&gt;Este es mi documento con una estructura muy sencilla no contiene atributos ni entidades... &lt;/Parrafo&gt;&lt;/Texto&gt;</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:

  1. Lee el nombre del fichero de la entrada standard
  2. Comprueba que el fichero existe y que el mismo se puede leer
  3. Almacena el contenido del fichero en una variable
  4. Decodifica entidades html
  5. Formatea el XML
  6. 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):

  1. Ejecutamos gedit
  2. Menu > Tools > Manage External Tool
  3. Agregamos una nueva herramienta externa y establecemos los valores como muestra la figura

gedit-external-tool

Abrimos nuestro fichero xml al cual le llamamos garbage.xml

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.

ppxml

Lecturas recomendadas

* Formatear ficheros XML

2 comentarios en “Formatear XML usando Python o PHP”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.