La complejidad artificial de los archivos OOXML (el caso XLSX)

Por Italo Vignoli

El artículo explicaba por qué un esquema XML artificialmente complejo, como el que usan los archivos de Microsoft 365 (antes Microsoft Office), es en realidad una herramienta sutil para atrapar a los usuarios, ya que es invisible e imposible de detectar sin un estudio profundo, y fue recogido por varios medios de comunicación especializados en TI. Probablemente, esto se debió a que explicaba un problema al que todos se enfrentan sin tener las herramientas para resolverlo de una manera accesible para todos.

Algunos de estos artículos provocaron un debate entre quienes apoyaban mi tesis y quienes defendían a Microsoft, los verdaderos campeones del bloqueo, que afirmaban que la complejidad del esquema XML no era artificial, sino más bien un reflejo de la complejidad de los propios documentos.

Esta complejidad está relacionada con diversos factores, como el tamaño (número de páginas), la estructura (texto, tablas, gráficos e imágenes), la gestión del contenido (introducción de datos por parte de varias personas y sistemas) y la personalización mediante metadatos. Estos factores influyen en la gestión, la clasificación y el almacenamiento del propio documento.

Los diferentes enfoques de la gestión de la complejidad entre ODF y OOXML

Los formatos ODF y OOXML manejan esta complejidad de maneras completamente diferentes. En el primer caso, el esquema XML busca simplificar el trabajo de los desarrolladores y usuarios al garantizar que se cumplan ambos conjuntos de requisitos. Los desarrolladores tienen a su disposición todas las herramientas descriptivas relacionadas con la complejidad del documento, y los usuarios pueden distinguir entre los elementos descriptivos y el contenido, ya que ambos casi siempre están separados. El contenido también es coherente en sintaxis con el documento.

En el segundo caso, el esquema XML no hace nada para simplificar la tarea del desarrollador y complica la tarea del usuario al reunir todos los elementos (descripción y contenido) sin ninguna lógica aparente. Esto hace que sea difícil o incluso imposible distinguirlos.

La complejidad del formato OOXML está relacionada con su diseño ya que se creó deliberadamente para que el formato fuera más difícil de implementar para los desarrolladores de software que no son de Microsoft. Los problemas de compatibilidad se deben a un auténtico «laberinto» de etiquetas que se utilizan incluso para el contenido más simple, lo que ata a los usuarios al ecosistema de Microsoft en el primer ejemplo de bloqueo basado en estándares.

A esto se suma el uso generalizado de descripciones complicadas, como las relacionadas con las fechas, que están vinculadas a un error introducido por Visicalc y que sigue presente en Excel 67 años después de su descubrimiento, y la separación arbitraria del contenido, como frases o incluso palabras que se dividen entre dos elementos de contenido. El formato refleja las estructuras de datos internas y las características heredadas de Microsoft Office. Utiliza codificaciones de idioma y unidades de medida no estándar, así como convenciones y reglas de nomenclatura inconsistentes entre módulos. También utiliza nombres de etiquetas confusos que son difíciles de descifrar.

El caso XLSX

Para ilustrar la diferencia de complejidad entre los esquemas XML ODF y OOXML, creé una sencilla hoja de cálculo que contiene fechas de mi vida que son significativas o irónicas. Entre ellas se incluyen la fecha en la que me rompí la nariz, la fecha en la que me la repararon y la fecha en la que me volví a casar con mi esposa en Las Vegas para celebrar el 30º aniversario de nuestro matrimonio con una ceremonia informal (una boda en una limusina).

Esta es una captura de pantalla de la hoja de cálculo:

Para realizar el análisis, dupliqué y renombré los dos archivos, sustituyendo la extensión original por «ZIP», y luego los descomprimí para crear dos carpetas que contenían todos los archivos de los respectivos esquemas XML.

La carpeta LibreOffice contiene tres subcarpetas y seis archivos, uno de los cuales se llama content.xml y llama inmediatamente la atención por su evocador nombre. Al abrirlo se revela todo su contenido, mientras que los demás archivos contienen instrucciones para mostrar correctamente la hoja de cálculo.

Esta es la parte significativa del archivo content.xml de LibreOffice:

<office:body>
<office:spreadsheet>
<table:calculation-settings table:case-sensitive=”false” table:automatic-find-labels=”false” table:use-regular-expressions=”false” table:use-wildcards=”true”>
<table:iteration table:maximum-difference=”0.0001″/>
</table:calculation-settings>
<table:table table:name=”Foglio1″ table:style-name=”ta1″>
<office:forms form:automatic-focus=”false” form:apply-design-mode=”false”/>
<table:table-column table:style-name=”co1″ table:default-cell-style-name=”ce2″/>
<table:table-column table:style-name=”co2″ table:default-cell-style-name=”ce4″/>
<table:table-column table:style-name=”co3″ table:number-columns-repeated=”16382″/>
<table:table-row table:style-name=”ro1″>
<table:table-cell table:style-name=”ce1″ office:value-type=”string” calcext:value-type=”string”>
<text:p>Event</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce3″ office:value-type=”string” calcext:value-type=”string”>
<text:p>Date</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>Was Born in Umbria</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”1954-08-12″ calcext:value-type=”date”>
<text:p>08/12/1954</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>Broke Nose in Rome</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”1965-01-18″ calcext:value-type=”date”>
<text:p>01/18/1965</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>University Degree in Milan</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”1978-11-19″ calcext:value-type=”date”>
<text:p>11/19/1978</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>First Job at Italian Touring Club</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”1981-01-10″ calcext:value-type=”date”>
<text:p>01/10/1981</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>Hired by Honeywell and Got 1st PC</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”1983-01-09″ calcext:value-type=”date”>
<text:p>01/09/1983</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>1st Wedding in Assisi</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”1984-08-09″ calcext:value-type=”date”>
<text:p>08/09/1984</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>BBC Show Interview in Birmingham</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”1987-02-17″ calcext:value-type=”date”>
<text:p>02/17/1987</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>Installed OpenOffice</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”2003-02-01″ calcext:value-type=”date”>
<text:p>02/01/2003</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>Repaired Nose in Rozzano</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”2008-12-04″ calcext:value-type=”date”>
<text:p>12/04/2008</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>Launched LibreOffice</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”2010-09-28″ calcext:value-type=”date”>
<text:p>09/28/2010</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro1″>
<table:table-cell office:value-type=”string” calcext:value-type=”string”>
<text:p>2nd Wedding in Las Vegas</text:p>
</table:table-cell>
<table:table-cell table:style-name=”ce7″ office:value-type=”date” office:date-value=”2014-08-08″ calcext:value-type=”date”>
<text:p>08/08/2014</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name=”ro2″ table:number-rows-repeated=”1048563″>
<table:table-cell table:number-columns-repeated=”2″/>
</table:table-row>
<table:table-row table:style-name=”ro2″>
<table:table-cell table:number-columns-repeated=”2″/>
</table:table-row>
</table:table>
<table:named-expressions/>
</office:spreadsheet>
</office:body>

Se trata de un archivo XML de complejidad razonable. Incluso alguien sin conocimientos técnicos es posible identificar el contenido de las dos columnas con poco de esfuerzo. El archivo tiene un formato comprensible para fechas, cadenas de texto y etiquetas (fila de tabla, celda de tabla, texto y valor de fecha).

La carpeta Microsoft 365 contiene tres subcarpetas y el archivo [Content_Types].xml. Al abrir este archivo se muestra información sobre los demás archivos, incluidos los de las subcarpetas. También muestra que el contenido se encuentra en el archivo sheet1.xml, que está oculto en la carpeta de hojas de cálculo, que a su vez está oculta en la carpeta xl. No hay ninguna razón técnica para este juego del escondite, salvo complicar la estructura interna del archivo XLSX.

La parte significativa del archivo sheet1.xml de Microsoft 365 es la siguiente:

<dimension ref=”A1:B12″/>
<sheetViews>
<sheetView tabSelected=”1″ workbookViewId=”0″>
<selection activeCell=”B1″ sqref=”B1:B1048576″/>
</sheetView>
</sheetViews>
<sheetFormatPr defaultRowHeight=”15″/>
<cols>
<col min=”1″ max=”1″ width=”34.140625″ style=”2″ bestFit=”1″ customWidth=”1″/>
<col min=”2″ max=”2″ width=”11.7109375″ style=”4″ bestFit=”1″ customWidth=”1″/>
</cols>
<sheetData>
<row r=”1″ spans=”1:2″>
<c r=”A1″ s=”1″ t=”s”>
<v>0</v>
</c>
<c r=”B1″ s=”3″ t=”s”>
<v>1</v>
</c>
</row>
<row r=”2″ spans=”1:2″>
<c r=”A2″ s=”2″ t=”s”>
<v>2</v>
</c>
<c r=”B2″ s=”4″>
<v>19948</v>
</c>
</row>
<row r=”3″ spans=”1:2″>
<c r=”A3″ s=”2″ t=”s”>
<v>3</v>
</c>
<c r=”B3″ s=”4″>
<v>23760</v>
</c>
</row>
<row r=”4″ spans=”1:2″>
<c r=”A4″ s=”2″ t=”s”>
<v>4</v>
</c>
<c r=”B4″ s=”4″>
<v>28813</v>
</c>
</row>
<row r=”5″ spans=”1:2″>
<c r=”A5″ s=”2″ t=”s”>
<v>5</v>
</c>
<c r=”B5″ s=”4″>
<v>29860</v>
</c>
</row>
<row r=”6″ spans=”1:2″>
<c r=”A6″ s=”2″ t=”s”>
<v>6</v>
</c>
<c r=”B6″ s=”4″>
<v>30560</v>
</c>
</row>
<row r=”7″ spans=”1:2″>
<c r=”A7″ s=”2″ t=”s”>
<v>7</v>
</c>
<c r=”B7″ s=”4″>
<v>30933</v>
</c>
</row>
<row r=”8″ spans=”1:2″>
<c r=”A8″ s=”2″ t=”s”>
<v>8</v>
</c>
<c r=”B8″ s=”4″>
<v>31825</v>
</c>
</row>
<row r=”9″ spans=”1:2″>
<c r=”A9″ s=”2″ t=”s”>
<v>9</v>
</c>
<c r=”B9″ s=”4″>
<v>37623</v>
</c>
</row>
<row r=”10″ spans=”1:2″>
<c r=”A10″ s=”2″ t=”s”>
<v>10</v>
</c>
<c r=”B10″ s=”4″>
<v>39550</v>
</c>
</row>
<row r=”11″ spans=”1:2″>
<c r=”A11″ s=”2″ t=”s”>
<v>11</v>
</c>
<c r=”B11″ s=”4″>
<v>40449</v>
</c>
</row>
<row r=”12″ spans=”1:2″>
<c r=”A12″ s=”2″ t=”s”>
<v>12</v>
</c>
<c r=”B12″ s=”4″>
<v>41859</v>
</c>
</row>
</sheetData>
<pageMargins left=”0.7″ right=”0.7″ top=”0.75″ bottom=”0.75″ header=”0.3″ footer=”0.3″/>

Es un archivo XML extremadamente críptico. Aparte de unas pocas etiquetas (col, row, sheetview y sheetdata), el esquema XML es completamente incomprensible. ¿Dónde están las fechas? ¿Dónde están las descripciones de los eventos?

En realidad están ahí, pero reto a cualquiera a encontrarlas a menos que sepa que Excel las describe con un número secuencial que comienza el 1 de enero de 1900. Para el 29 de febrero de 1900, añade uno, a pesar de que se trata de un día «fantasma» que el programa —incompatible con el calendario gregoriano, una norma reconocida incluso por los chinos y los musulmanes— sigue considerando obstinadamente como existente, a pesar de que Bob Bemer descubrió el «error del año bisiesto» en 1958.

Por lo tanto, en Excel, 19948 corresponde al 12 de agosto de 1954, pero en realidad es el 13 de agosto de 1954. Las otras fechas son, obviamente, 23 760; 28 813; 29 860; 30 560; 30 933; 31 825; 37 623; 39 550; 40 449; y 41 859. Esto es intuitivo y fácil de calcular y, sobre todo, viene impuesto por la complejidad del documento. Tonterías.

Sin embargo, el misterio de las descripciones de los eventos sigue sin resolverse. Según sheet1.xml, no existen, ya que no aparecen de ninguna manera, ni siquiera como referencia. Es como si la hoja de cálculo consistiera únicamente en la segunda columna.

Así que vuelvo al archivo [Content_Types].xml y abro los archivos XML en el orden en que aparecen, buscándolos en las subcarpetas.

<Types xmlns=”http://schemas.openxmlformats.org/package/2006/content-types”>
<Default Extension=”rels” ContentType=”application/vnd.openxmlformats-package.relationships+xml”/>
<Default Extension=”xml” ContentType=”application/xml”/>
<Override PartName=”/xl/workbook.xml” ContentType=”application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml”/>
<Override PartName=”/docProps/core.xml” ContentType=”application/vnd.openxmlformats-package.core-properties+xml”/>
<Override PartName=”/docProps/app.xml” ContentType=”application/vnd.openxmlformats-officedocument.extended-properties+xml”/>
<Override PartName=”/xl/worksheets/sheet1.xml” ContentType=”application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml”/>
<Override PartName=”/xl/theme/theme1.xml” ContentType=”application/vnd.openxmlformats-officedocument.theme+xml”/>
<Override PartName=”/xl/styles.xml” ContentType=”application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml”/>
<Override PartName=”/xl/sharedStrings.xml” ContentType=”application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml”/>
</Types>

Justo cuando estaba a punto de perder la esperanza, finalmente encontré las descripciones de los eventos en el archivo sharedStrings.xml. El archivo contiene lo siguiente:

<sst xmlns=”http://schemas.openxmlformats.org/spreadsheetml/2006/main” count=”13″ uniqueCount=”13″>
<si>
<t>Event</t>
</si>
<si>
<t>Date</t>
</si>
<si>
<t>Was Born in Umbria</t>
</si>
<si>
<t>Broke Nose in Rome</t>
</si>
<si>
<t>University Degree in Milan</t>
</si>
<si>
<t>First Job at Italian Touring Club</t>
</si>
<si>
<t>Hired by Honeywell and Got 1st PC</t>
</si>
<si>
<t>1st Wedding in Assisi</t>
</si>
<si>
<t>BBC Show Interview in Birmingham</t>
</si>
<si>
<t>Installed OpenOffice</t>
</si>
<si>
<t>Repaired Nose in Rozzano</t>
</si>
<si>
<t>Launched LibreOffice</t>
</si>
<si>
<t>2nd Wedding in Las Vegas</t>
</si>
</sst>

Si Sheet1.xml era críptico, esto es totalmente incomprensible. Me gustaría saber cómo se relacionan los eventos con las fechas dentro del archivo sheet1.xml a través de las diferentes etiquetas utilizadas en los dos archivos: <t> y <v>. No hay referencias cruzadas que vinculen los dos elementos, y si las hay, reto a cualquiera a que me las explique de una manera que pueda entender y justificar el misterioso formato de estas referencias.

Lamentablemente, la realidad es la que ya he intentado explicar sin entrar en detalles técnicos, como he hecho en esta publicación y haré en la siguiente dedicada al caso DOCX. Microsoft ha desarrollado un formato innecesariamente complejo —si LibreOffice puede manejar la información de forma más sencilla, no entiendo por qué Microsoft 365 no puede hacer lo mismo— con el objetivo de dificultar al máximo la emulación del formato OOXML sin ingeniería inversa, muy utilizada en algunos países.

Además, las suites ofimáticas que utilizan ingeniería inversa para adoptar OOXML como formato nativo solo ayudan a Microsoft a defender su cuota de mercado promoviendo un formato propietario que va en contra de los intereses de los usuarios y de su derecho a la propiedad y el control del contenido que han desarrollado, lo que generalmente se conoce como soberanía digital.

Los usuarios deben aprender a proteger sus derechos eligiendo un formato abierto y estándar como ODF. Esto garantiza el control sobre el contenido y todo lo que ello conlleva, incluida la protección de la privacidad, la gestión adecuada de los datos sensibles y la capacidad de decidir qué compartir y con quién.

Se trata de un formato cuyo proceso de desarrollo, características y versión son conocidos, y cuya descripción se corresponde con lo que ocurre en la PC del usuario, por lo que incluso el usuario menos técnico puede entender cuándo se produce un problema y, en muchos casos, resolverlo.

En resumen, es el formato de documento estándar que todos quisiéramos tener, pero que solo una minoría utiliza debido al desconocimiento de la realidad del formato OOXML y a la confianza mesiánica que muchos tienen en Microsoft. Esto les lleva a creer que no puede haber una estrategia comercial detrás del formato de documento que proteja los intereses de la empresa a expensas de los usuarios.

Deja una respuesta

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

Acepto la Política de privacidad