Xml namespaces

En ocasiones, documentos XML relativos a diferentes temas, pueden tener los mismos nombres. Este problema se agrava cuando hay que combinar documentos que puedan provocar ambigüedades. Para ello se introducen los namespaces.

Una compañía puede crear un documento XML que describe el mundo en sus propios términos. Por ejemplo, si una compañía considera que una <adquisición> puede contener cierto conjunto de información, mientras que otra compañía considera que debe tener otro tipo de información, ambas compañías pueden crear sus documentos sin problemas. El problema está cuando estos documentos dejan de estar separados. Por ejemplo, pensemos en los posibles significados de un elemento llamado <título>.

Prefijos

La mejor manera de resolver esto es tener un nombre único para cada elemento. Por ejemplo, si mezclamos en nuestro documento etiquetas XML propias y etiquetas HTML que no queremos que se mezclen, se puede resolver con una convención de nombres donde cada elemento de nuestro documento XML tiene su propio prefijo, y cada etiqueta de HTML tiene otro prefijo. Por ejemplo, observa el siguiente código:

<?xml version="1.0"?> <person> <name> <title>Don</title> <first>Juan</first> <middle>García</middle> <last>Pérez</last> </name> <position>Vicepresidente de Marketing</position> <resume> <html> <head><title>Resumen de Juan García Pérez</title></head> <body> <h1>Juan García</h1> <p>Juan es una buena persona,¿No?</p> </body> </html> </resume> </person>

Resulta ambiguo. La aplicación destinatario confundiría el título "Don" con el título "Resumen de Juan...". Utilizando prefijos, quedaría del siguiente modo:

<?xml version="1.0"?> <pers:person> <pers:name> <pers:title>Don</pers:title> <pers:first>Juan</pers:first> <pers:middle>García</pers:middle> <pers:last>Pérez</pers:last> </pers:name> <pers:position>Vicepresidente de Marketing</pers:position> <pers:resume> <xhtml:html> <xhtml:head><xhtml:title>Resumen de Juan García Pérez</xhtml:title></xhtml:head> <xhtml:body> <xhtml:h1>Juan García</xhtml:h1> <xhtml:p>Juan es una buena persona,¿No?</xhtml:p> </xhtml:body> </xhtml:html> </pers:resume> </pers:person>

Aunque sea un poco engorroso, es efectivo, ya que un analizador sintáctico diferencia perfectamente <pers:title> de <xhtml:title>.

El inconveniente que tiene es que ya no se están usando etiquetas correctas xhmtl. Los navegadores no entenderán <xhmtl:p> como una etiqueta <p>. Para que el navegador lea correctamente el código xhmtl, antes habría que renombrar cada elemento.

Hemos creado dos categorías. La categoría de elementos pers y la categoría de elementos xhtml. A estas categorías le llamamos namespace. Pero ¡OJO! las categorías estan relacionadas con el vocabulario, no con el tipo de documento. Es decir, el namespace distingue qué nombres están en el namespace, pero no que significan o como deben mezclarse entre sí. Es una sencilla "bolsa de nombres".

¿Y ya está?

¿Qué ocurriría si dos compañías utilizan el mismo prefijo para dos vocabularios diferentes? Estamos entonces en las mismas. Para evitar esta ambigüedad, podemos hacer uso de las "no ambigüedades" de los nombres de dominio de Internet. En internet se suele hablar de URL (Universal Resource Locator) para describir la localización de un recurso. Por ejemplo, supongamos que dos compañías emplean el prefijo "pers" para conceptos distintos. La primera compañía tiene registrado el dominio www.mauriciomatamala.net. La segunda tiene registrado www.otrodominio.info. Entonces, las ambigüedades desaparecen en el elemento "name" con los siguientes prefijos:

<{http://www.mauriciomatamala.net/pers}name> <{http://www.otrodominio.info/pers}name>

¡OJO! http://www.mauriciomatamala.net/pers es solo un nombre no una URL. Sólo se utiliza con efectos de identificación.

Incluso si dentro de una misma compañía hay namespaces con el mismo nombre que tienen significados diferentes, se puede dar una solución elegante. Por ejemplo, el departamento de ventas y el de publicidad tienen dos namespaces diferentes llamados "pers". En tal caso, los prefijos podrían ser como los siguientes, para la etiqueta nombre:

<{http://www.otrodominio.info/ventas/pers}name> <{http://www.otrodominio.info/publicidad/pers}name>

La especificación de las namespaces está en http://www.w3.org/TR/REC-xml-names/

El mejor modo de establecer prefijos es mediante "nombres cualificados". Estos nombres cualificados consisten en dos partes: parte local, es decir, el nombre del elemento y prefijo del namespace, que especifica a que namespace pertenece el prefijo. Observa el siguiente ejemplo:

<pers:name xmlns:pers="http://www.mauriciomatamala.net/pers">

Una vez definido el namespace, éste se respeta para los elementos descendientes. Por ejemplo:

<pers:persona xmlns:pers="http://www.mauriciomatamala.net/pers"> <pers:nombre> <pers:título>Don</pers:título> </pers:nombre> </pers:persona>

No poner prefijo a una etiqueta implica decir que no pertenece a ningún namespace.

Si dentro de un elemento se van a usar más un namespace, se pueden declarar todos en la misma etiqueta. Después, se hará uso del prefijo en cada elemento, según convenga. Por ejemplo:

<?xml version="1.0"?> <pers:person xmlns:pers="http://www.mauriciomatamala.net/pers" xmlns:html="http://www.w3.org/1999/xhtml"> <pers:name> <pers:title>Don</pers:title> <pers:first>Juan</pers:first> <pers:middle>García</pers:middle> <pers:last>Pérez</pers:last> </pers:name> <pers:position>Vicepresidente de Marketing</pers:position> <pers:resume> <xhtml:html> <xhtml:head><xhtml:title>Resumen de Juan García Pérez</xhtml:title></xhtml:head> <xhtml:body> <xhtml:h1>Juan García</xhtml:h1> <xhtml:p>Juan es una buena persona,¿No?</xhtml:p> </xhtml:body> </xhtml:html> </pers:resume> </pers:person>

Internamente, los analizadores sintácticos sustituyen los prefijos por el URL correspondiente. Un prefijo no significa nada para XML, y lo que realmente le importa es el nombre de dominio asociado a él.

Namespaces por defecto

Para no tener que estar todo el rato poniendo prefijos, se pueden indicar un namespace por defecto para todas las etiquetas. Observa el siguiente ejemplo:

<person xmlns="http://www.otrodominio.info/pers"> <name> <title>Don</title> </name> </person>

Observa que no hay prefijo definido. Por ello, todas las etiquetas que no tienen prefijo y son descendientes de "person" pertenecen al mismo namespace.

Solo puede haber un namespace por defecto. Se pueden definir más namespaces pero siempre indicando un prefijo. Por ejemplo:

<person xmlns="http://www.otrodominio.info/pers" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <name/> <xhtml:p>This is XHTML</xhtml:p> </person>

En este ejemplo el namespace por defecto es "http://www.otrodominio.info/pers". Todas las etiquetas pertenecen a este namespace, salvo <xhtml:p> que pertenece al namespace "http://www.w3.org/1999/xhtml".

Ejercicio 12. Partiendo del siguiente código XML, haz las modificaciones necesarias para introducir un namespace por defecto y otro por prefijo. Elimina los prefijos innecesarios. Después pruébalo en un navegador.

<?xml version="1.0"?> <pers:person> <pers:name> <pers:title>Don</pers:title> <pers:first>Juan</pers:first> <pers:middle>García</pers:middle> <pers:last>Pérez</pers:last> </pers:name> <pers:position>Vicepresidente de Marketing</pers:position> <pers:resume> <xhtml:html> <xhtml:head><xhtml:title>Resumen de Juan García Pérez</xhtml:title></xhtml:head> <xhtml:body> <xhtml:h1>Juan García</xhtml:h1> <xhtml:p>Juan es una buena persona,¿No?</xhtml:p> </xhtml:body> </xhtml:html> </pers:resume> </pers:person>

NOTA: Para el namespace de xhtml, utiliza el namespace "http://www.w3.org/1999/xhtml", visualiza el código. ¿Qué ocurre si en vez de este namespace utilizas otro como por ejemplo "http://www.otracosa.org/1999/xhtml"?

No es necesario declarar todos los namespaces en el elemento raíz. Se puede hacer en cualquier etiqueta descendiente. Esto se hará siempre que mejore la legibilidad del documento. Por ejemplo:

<person xmlns="http://www.otrodominio.info/pers"> <name/> <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">This is XHTML</xhtml:p> </person>

De hecho se pueden indicar namespaces por defecto anidados, de modo que en cada elemento se aplica el namespace por defecto más concreto. Por ejemplo:

<person xmlns="http://www.otrodominio.info/pers"> <name/> <p xmlns="http://www.w3.org/1999/xhtml"> This is <strong>XHTML</strong> </p> </person>

En este caso, las etiquetas <person> y <name> pertenecen al dominio "otrodominio.info". Pero las etiquetas <p> y <strong> pertenecen al namespace "http://www.w3.org/1999/xhtml".

Ejercicio 13. Modifica el código del ejercicio 12, para que los namespaces no estén todos definidos en el elemento raíz. Haz que tanto el namespace "http://www.undominio.info/pers" como "http://www.w3.org/1999/xhtml" sean namespaces por defecto en sus ámbitos correspondientes.>

Entrega la actividad 13 como Act13.xml

Para cancelar un namespace por defecto en un elemento concreto, podemos utilizar el siguiente atributo: xmlns="". De este modo, el elemento concreto no pertenecerá a ningún namespace, así como sus descendientes. En cualquier caso, un documento que emplea diferentes namespaces, debería siempre definir a que namespace pertenece cada elemento, por lo que esto es para casos muy concretos.

Atributos y namespaces

Generalmente los atributos no tienen namespace, ya que están adscritos a un elemento concreto. Sin embargo, si se están utilizando prefijos, en ciertos casos es preciso especificar un prefijo para los atributos. Por ejemplo, observa los dos códigos siguientes:

<a:person xmlns:a="http://www.undominio.info/pers"> <a:name a:id="30"> <a:title>Don</a:title> </a:name> <a:person> <a:person xmlns:a="http://www.undominio.info/pers"> <a:name id="30"> <a:title>Don</a:title> </a:name> <a:person>

En general son el mismo código, pero para ciertas transformaciones (con XSLT por ejemplo) es preciso especificarlo. Por ello, en caso de duda, se añaden los prefijos a los atributos.

Ejercicio 14. Añade al ejercicio 12 un atributo a la etiqueta p. En concreto, añádele el siguiente: style="FONT-FAMILY: Arial".

Entrega la actividad con el nombre Act14.xml

Ejercicio 15. Crea un documento XML donde se almacena información sobre Libros en papel de la empresa A y electrónicos de la empresa B. Crea un namespace para cada empresa, y poder distinguir libro en papel de la empresa A, de libro electrónico de la empresa B, y rellena el documento con los siguientes datos. Para ello deberás tomar decisones respecto a las etiquetas que utilizarás.

Entrega la actividad con el nombre Act15.xml

Libro electrónico: Beginning XML. 4th edition. Ed Wiley. David Hunter et al. 2007. Formato pdf. Tamaño 14 MB.

Libro papel: Configuración de Infraestructura de red de Windows Server 2008. Tony Nothrup. Ed Microsoft Press. 2008. Pasta blanda. CD incluido.

Saludos.