Eliminar elementos de un XML utilizando XSLT

Introducción

XSLT (eXtensible Stylesheet Language Transformations) es un estándar de la W3C basado en XML que permite transformar un XML en un documento de otro tipo: otro XML, HTML, texto, etc. El estándar XSLT está basado en plantillas (templates) que no son más que XMLs que cumple un esquema determinado. Dentro de estos XMLs, se describe cómo transformar los diferentes elementos que componen el documento de origen, utilizando el estándar XPath para asociar los elementos del documento de origen a la salida de la transformación

Una transformación XLST está compuesta por los siguientes elementos:

  • Un documento XML de origen
  • Una plantilla XLST
  • Un motor de procesamiento de plantillas XSLT
  • Un documento resultante de la transformación

El motor toma como entrada una plantilla y un XML de origen y retorna como resultado otro documento (ver diagrama en Wikipedia).

El lenguaje de XSLT no es imperativo, las acciones a realizar se declaran en un conjunto de reglas que definen cómo actuar cuando un nodo coincide con la expresión XPath definida para esa regla. De esta forma el motor, luego de haber procesado el documento de entrada y armado una especie de árbol con esa estructura, parte del nodo raíz del XML y ejecuta las reglas que mejor apliquen para cada elemento, siendo el resultado de esta ejecución el documento de salida.

Eliminar elementos del XML

Si queremos eliminar elementos de un XML existente, podemos utilizar una plantilla XSLT para transformarlo y eliminar el contenido que no necesitemos.

Veamos el siguiente ejemplo: tenemos un XML con un conjunto de empleados, en donde cada elemento tiene un nombre (elemento compuesto), un e-mail y una relación de dependencia con otro(s) empleado(s), que puede ser como subordinado o como jefe. Queremos procesar ese XML y retornar otro XML que
no contenga el apellido o información de dependencia dentro de la empresa. Además, queremos sacar a “Big Boss” de esa lista.

El XML de entrada es el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<personnel>
    <person id="Big.Boss">
        <name>
            <family>Boss</family>
            <given>Big</given>
        </name>
        <email>chief@email.com</email>
        <link subordinates="one.worker two.worker three.worker four.worker five.worker"/>
    </person>
    <person id="one.worker">
        <name>
            <family>Worker</family>
            <given>One</given>
        </name>
        <email>one@email.com</email>
        <link manager="Big.Boss"/>
    </person>
    <person id="two.worker">
        <name>
            <family>Worker</family>
            <given>Two</given>
        </name>
        <email>two@email.com</email>
        <link manager="Big.Boss"/>
    </person>
    <person id="three.worker">
        <name>
            <family>Worker</family>
            <given>Three</given>
        </name>
        <email>three@email.com</email>
        <link manager="Big.Boss"/>
    </person>
    <person id="four.worker">
        <name>
            <family>Worker</family>
            <given>Four</given>
        </name>
        <email>four@email.com</email>
        <link manager="Big.Boss"/>
    </person>
    <person id="five.worker">
        <name>
            <family>Worker</family>
            <given>Five</given>
        </name>
        <email>five@email.com</email>
        <link manager="Big.Boss"/>
    </person>
</personnel>

Una solución para el problema sería tener una plantilla XLST como la siguiente:

<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

	<xsl:output omit-xml-declaration="yes" method="xml" media-type="xml" indent="yes"/>
	<xsl:strip-space elements="*"/>

	<xsl:template match="node()|@*">
		<xsl:copy>
			<xsl:apply-templates select="node()|@*"/>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="/personnel/person/name/family"/>
	<xsl:template match="/personnel/person/link"/>
	<xsl:template match="/personnel/person[@id='Big.Boss']"/>
</xsl:stylesheet>

En el XLST tenemos por un lado los <xsl:template> que aplican para casos bien puntuales (cuando el nodo visitado es coincide con la expresión XPath) y actúan ignorando ese elemento sin escribirlo al documento de salida. Por otro lado está <xsl:template match="node()|@*">, que actúa como regla para el resto de los nodos, copiando su contenido y continuando la transformación en sus hijos.

En <xsl:output> configuramos el tipo de documento de salida, la indentación, etc. Si interesa que el XML resultante quede del menor tamaño posible, podemos eliminar la indentación (indent="no") y ahorrarnos alguna línea y algún tabulador.

La línea que contiene <xsl:strip-space elements="*"/> elimina las líneas en blanco que deja la transformación en donde originalmente estaban ubicados los elementos eliminados.

El resultado de la transformación es el siguiente:

<personnel>
   <person id="one.worker">
      <name>
         <given>One</given>
      </name>
      <email>one@email.com</email>
   </person>
   <person id="two.worker">
      <name>
         <given>Two</given>
      </name>
      <email>two@email.com</email>
   </person>
   <person id="three.worker">
      <name>
         <given>Three</given>
      </name>
      <email>three@email.com</email>
   </person>
   <person id="four.worker">
      <name>
         <given>Four</given>
      </name>
      <email>four@email.com</email>
   </person>
   <person id="five.worker">
      <name>
         <given>Five</given>
      </name>
      <email>five@email.com</email>
   </person>
</personnel>

Conclusión

XSLT nos da una infinidad de posibilidades a la hora de transformar un XML a la salida deseada. Este es un ejemplo bastante simple, pero con 16 líneas de XLST y algunas más de código para instanciar un procesador y configurarle la transformación, cumplimos el objetivo con la posibilidad de cambiar o expandir el XML original sin afectar el documento transformado. Además tiene un plus haberlo logrado de forma eficiente y basándonos en estándares.

Referencias

http://en.wikipedia.org/wiki/XSLT
http://www.w3.org/TR/xslt

Bookmark the permalink.

4 respuestas a Eliminar elementos de un XML utilizando XSLT

  1. Tom says:

    Muy util.

    ¿Algun programa para aplicar una XSLT a varios XMLs a la vez?

    • jarrarte says:

      Hola Tom. Para hacer una transformación a varios XMLs con el mismo XSLT puedes usar un editor XML. Uno que está muy bueno es el (http://www.oxygenxml.com/) pero es pago y el trial dura sólo 30 días. Otra opción es hacer un programita que cargue la plantilla XSLT, levante los diferentes XMLs y vaya aplicando la transformación a cada uno de ellos.

      Espero haber respondido tu pregunta. Saludos,
      José

  2. Ramon says:

    Si yo recibo parámetros, ¿cómo puedo hacerlo?

    Tengo el siguiente xml:

    2151075
    Bases de datos
    15-P
    2016-05-30

    Juan
    Dominguez
    Guido

    /escolar/Datos/xml/planeacion/2151075-15-P-CD02.xml

    2151123
    Filosofia
    16-P
    2016-06-01

    Miguel
    Sanchez
    Perez

    /escolar/Datos/xml/planeacion/2151123-16-P-CI01.xml

    Necesito hacer borrado de de manera completa, es decir, borrar toda una planeacion con todo y los nodos que lleva

    Recibo como parámetros el nombre, los apellidos, clave, trimestre y uri

    ¿cómo puedo hacer el borrado de una planeación según lo que reciba como parámetro?

  3. Kaatelars says:

    Y si necesito eliminar todo un nodo ¿cómo lo hago?

Deja un comentario

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