Carrito de compras

Visualización de XML utilizando control WebBrowser de WindowsForms

21 oct. Desarrollador de software

.NET WINDOWS FORMS

Código fuente: https://github.com/batressc/WinFormsWebBrowserXML

Introducción – El desencanto

Buscando una forma elegante de simular un visor de archivos XML para Windows Forms (sí lo sé, pero no quería utilizar el RichTextBox o el TextBox normal), me dediqué a buscar mediante Google cómo utilizar el control WebBrowser para dicho fin.

Después de revisar varios artículos no obtenía una respuesta satisfactoria ya que todos mencionaban que había que realizar funciones o métodos complejos, transformaciones de Streams, creación de código HTML y hasta el uso de XSD. Acá unos cuantos ejemplos:

Convencido que esto no debería ser tan complejo, decidí revisar en la documentación de MSDN (la cual me encanta) los métodos disponibles del control y de ellos el más adecuado fue DocumentText. Según la documentación:

Obtiene o establece el contenido HTML de la página que se muestra en el control WebBrowser

Okey. Directo, simple y comprensible. Apelando un poco a la suerte, recordé que Internet Explorer formatea de una forma visualmente agradable los XML, por lo que este método debería funcionar de forma equivalente a que cargara el archivo mediante el menú “Abrir” de la aplicación (la hipótesis).

Armé la versión inicial de mi visor con un control TextBox, un WebBrowser y un Button para ejecutar la acción: Seleccioné de mi archivo de ejemplo el texto XML, copy/paste en mi TextBox de entrada, click en el botón Button1 y… todo en blanco…

¿Será posible que efectivamente tendría que utilizar uno de los métodos extravagantes para mostrar un simple archivo XML? ¿Habré hecho algo mal? ¿Me faltará algún paso? Una serie de dudas asaltaban mi cabeza, aún preguntándome si realmente merecía ser un programador por invertir una buena cantidad de tiempo en un problema tan trivial. A pesar de ser arrastrado y vapuleado por el mar de dudas, recordé que la semana pasada tuve un problema similar al realizar el copy/paste de un texto de ejemplo: El caracter BOM.

Después de hacer un rápido debugging y convertir la cadena de entrada a un arreglo de bytes confirmé mis sospechas: De alguna forma malévola y perversa se habían logrado colar en mi texto de ejemplo dichos caracteres ( ?(????)? ). ¡Una vez corregido, todo funcionó a la perfección! A raíz de este episodio, decidí mejorar mi ejemplo básico y hacer una simulación de dicha situación.

¿Y qué es el BOM?

La W3C en su sección de preguntas y respuestas (artículos en inglés, ver pregunta 1 y pregunta 2) nos explica de forma clara qué es, para qué sirve y el por qué ya no debe utilizarse. En resumen podemos decir:

Byte Order Mark (BOM) es una combinación de bytes que se escriben al principio de un archivo los cuales actúan como firma para indicar qué codificación Unicode se está utilizando o el orden de los bytes del archivo de texto (endianness).

Otros datos de interés:

  • Su representación unicode es: U+FEFF
  • Byte Order Mark es un álias del caracter llamado ZERO WIDTH NO-BREAK SPACE (ZWNBSP) (What?!)
  • A continuación se muestra el listado de codificaciones y sus BOM correspondientes:

Simulación de XML con/sin BOM y visualización en control WebBrowser 

Los puntos que cubre la aplicación son los siguientes:

  • Visualización de un archivo XML utilizando el control WebBrowser
  • Carga de XML a partir de archivos.
  • Renderizado del archivo XML en codificación UTF-8 con y sin BOM
  • Edición de contenido a mostrar (StringValue)
  • Visualización de arreglo de bytes y caracteres de la cadena XML a utilizar (para examinar la existencia del BOM)

Para poder utilizar el control PropertyGrid primeramente debemos definir una clase con las propiedades que deseamos exponer. Es importante marcar como privados los setters de los arreglos de bytes y caracter para evitar que sean modificables en la interfaz de usuario. Al momento de realizar un cambio en la cadena de entrada ( StringValue ) realizamos la conversión a sus representaciones de arreglo correspondientes.

Creamos la función auxiliar saveCacheXML  la cual realiza lo siguiente:

  1. Asignación de la cadena de entrada en la variable global _xmlSample (se mantiene invariable hasta que se introduzca un nuevo valor)
  2. Asignación de la cadena en propiedad StringValue para que se realicen las transformaciones correspondientes como arreglo de bytes y caracteres.
  3. Asignación del objeto _data en el control PropertyGrid  para visualización del usuario.

Para agregar el caracter BOM en el XML de entrada utilizamos la función UTF8String :

  • Primeramente debemos indicar si utilizaremos BOM. Para ello establecemos enviamos el valor true  en el constructor de la clase UTF8Encoding (línea 2).
  • Si aplica, almacenamos la representación de bytes del BOM en el arreglo bytesBOM . Para obtenerla utilizamos el método GetPreamble (línea 8).
  • Obtenemos la representación de bytes de la cadena XML de entrada y la almacenamos en el arreglo de bytes bytesData (línea 11).
  • Dependiendo del caso, almacenamos en bytesString  los datos con BOM (línea 14) o sin BOM (línea 16).
  • Asignamos en la propiedad StringValue  la cadena generada a partir de bytesString .

Utilizamos la función UTF8String  para generar el XML con o sin BOM, luego mediante la propiedad DocumentText  lo renderizamos en el control WebBrowser:

Condiciones para visualizar XML en control WebBrowser

Algo que no se menciona en la documentación del MSDN acerca de este punto es que la cadena de entrada XML debe cumplir ciertas características para poder renderizarse correctamente. Veamos cada una de ellas:

Condición #1: Debe especificarse el prólogo XML

“¿El qué, el qué?” Esa fue la misma expresión que tuve al buscar cómo se llamaba la etiqueta inicial <?xml version="1.0"?> . Como se indica en la especificación de la W3C este elemento es de carácter opcional, pero debería agregarse. Para el caso del control WebBrowser es necesario indicarlo, sino el contenido será interpretado como HTML:

Condición #2: Debe ser un XML bien formado

Si el archivo XML no cumple con los lineamientos de la especificación no es posible visualizarlo. Como se puede observar en la imagen a pesar que agregamos el prólogo XML y no hay errores de sintaxis (emparejamiento de etiquetas), como tenemos dos nodos padre no cumplimos con la especificación y por lo tanto no es visible el documento. En el notepad vemos el código fuente cargado en el control (click derecho, ver código fuente).

Condición #3: La cadena XML NO debe poseer el caracter BOM

He aquí la raíz de este artículo. Si el caracter BOM está presente en la cadena que se asigna en la propiedad DocumentText  no se visualizará el documento.  Para este ejemplo, presionamos click en el botón “UTF-8 with BOM”, como observamos en la imagen no se muestra ningún contenido, ni siquiera aparece la opción de “Ver código fuente”, no se ha realizado carga de datos en el control. Si examinamos la propiedad DataByte veremos los valores 239, 187 y 191  que son la representación decimal de la firma BOM (ver cuadro de codificaciones).

Una vez cumplimos las condiciones listadas anteriormente, al presionar el botón “UTF-8” podremos visualizar nuestro archivo XML (¡por fin!):

Ing. Luis Gustavo Fernández Batres | Development Engineer Consultant | Ingeniero Informático

¿Te gustó? Entonces comparte la publicación: