Espais de noms
L'espai de noms en XML ens serveix per a diferenciar dues etiquetes que tenen el mateix nom, tot i que el seu origen i significat pot ser totalment diferent. A mode d'exemple, suposem que tenim el següent document XML.
<?xml version="1.0" encoding="UTF-8" ?>
<menu>
<starters>
<dish>
<name>Tomato soup</name>
<price>2.0</price>
<ingredients>
<name>tomato</name>
<name>onion</name>
<name>carrot</name>
<!-- More ingredients ... -->
</ingredients>
</dish>
<dish>
<name>French onion soup</name>
<price>2.0</price>
<ingredients>
<name>onion</name>
<name>butter</name>
<!-- More ingredients ... -->
</ingredients>
</dish>
</starters>
<main>
<!-- More dishes -->
</main>
<!-- More menu elements ... -->
</menu>
Tot i que per una persona humana pot diferenciar l'etiqueta name d'un plat (dish) o d'un ingredient, per un sistema informàtic no és fàcil saber quin és quin. Utilitzant un espai de noms facilitem que un sistema informàtic pugui diferenciar de forma clara entre les dues etiquetes, facilitant així la feina del programador.
Video: Utilització espais de noms - nodes mateix nom (fins segon 23)
Declaració espai de noms
Un espai de noms està format per una URL o URN que especifica quina és la identificació d'aquest espai de noms. Aquesta URL ha de ser única: dues empreses no han d'utilitzar el mateix espai de noms. Per aquest motiu, moltes vegades s'utilitza el nom de domini de l'empresa per a especificar l'espai de noms. Associat a l'espai de noms podem definir un prefix. Utilitzarem el prefix per a especificar quines són les etiquetes que pertanyen a l'espai de noms definit.
La declaració de l'espai de noms es fa dins una etiqueta XML. Per a declarar un espai de noms utilitzem la següent sintaxis:
xmlns[:prefix]="URL | URN"
on
xmlns -> paraula clau que utilitzem per a indicar al processador (parser) que es declara un espai de noms. :prefix -> nom que volem associar a aquest espai de noms . URL o URN -> identificador en format de URL o URN de l'espai de noms que s'està definint.
<?xml version="1.0" encoding="UTF-8" ?>
<menu
xmlns:d="http://www.mynamespace.org/dish"
xmlns:i="http://www.mynamespace.org/ingredients" >
<starters>
<d:dish>
<d:name>Tomato soup</d:name>
<d:price>2.0</d:price>
<i:ingredients>
<i:name>tomato</i:name>
<i:name>onion</i:name>
<i:name>carrot</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</d:dish>
<d:dish>
<d:name>French onion soup</d:name>
<d:price>2.0</d:price>
<i:ingredients>
<i:name>onion</i:name>
<i:name>butter</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</d:dish>
</starters>
<main>
<!-- More dishes -->
</main>
<!-- More menu elements ... -->
</menu>
En el document anterior s'han declarat dos espais de noms
xmlns:d="http://www.mynamespace.org/dish"
xmlns:i="http://www.mynamespace.org/ingredients"
un per a dish i un altre per a ingredients. Els prefixos associats a cada un d'ells és "d" per a l'espai de noms referent a plats (dish) i "i" per a l'espai de noms referent a ingredients.
Prefix en l'espai de noms
El prefix és un apuntador a l'espai de noms al qual està associat. Això vol dir que podem utilitzar el prefix com a una referència a l'espai de noms. A la pràctica s'utilitza aquest prefix per a indicar a quin espai de noms pertany cada una de les etiquetes. El format general és:
<[prefix:]nomEtiqueta [atributs] >[contingut]</[prefix:]nomEtiqueta>
Si s'utilitza un prefix d'espai de noms en l'obertura d'etiqueta, obligatòriament cal utilitzar aquest prefix en el tancament de l'etiqueta: en cas contrari el "parser" XML ens dirà que el document no està ben format. En el codi anterior es pot veure l'utilització de diferents prefixos en diferents etiquetes.
Àmbit de l'espais de noms
L'espai de noms estarà vigent per a l'etiqueta on es declara i per a tots els descendents d'aquesta etiqueta. Si es declara l'espai de noms al node arrel del document XML, aquest espai de noms estarà disponible per a tots els elements que conformin el document XML. En el cas del nostre document XML, una possible reestructuració seria:
<?xml version="1.0" encoding="UTF-8" ?>
<menu xmlns:d="http://www.mynamespace.org/dish">
<starters>
<d:dish>
<d:name>Tomato soup</d:name>
<d:price>2.0</d:price>
<i:ingredients xmlns:i="http://www.mynamespace.org/ingredients" >
<i:name>tomato</i:name>
<i:name>onion</i:name>
<i:name>carrot</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</d:dish>
<d:dish>
<d:name>French onion soup</d:name>
<d:price>2.0</d:price>
<i:ingredients xmlns:i="http://www.mynamespace.org/ingredients" >
<i:name>onion</i:name>
<i:name>butter</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</d:dish>
</starters>
<main>
<!-- More dishes -->
</main>
<!-- More menu elements ... -->
</menu>
A diferència del codi inicial, es declara l'espai de noms relacionat amb ingredients en l'etiqueta ingredients. En la primera declaració, l'espai de noms només estarà vigent per a l'etiqueta ingredients i pels elements que estiguin continguts dins d'aquesta etiqueta: l'espai de noms referent a ingredients no es pot utilitzar en l'etiqueta dish o main , ja que no estan contingudes dins l'etiqueta on s'ha declarat l'espai de noms. Per aquest motiu s'ha hagut de tornar a declarar l'espai de noms pel segon plat del document XML.
Tot i que els dos codis són equivalents, la repetició de l'espai de noms en cada una de les etiquetes ingredients fa que el codi sigui una mica més complex. En aquest cas , la primera solució seria millor.
Espai de noms per defecte (default namespaces)
Els espais de nom per defecte són aquells que no tenen associat cap prefix. Tot i pertànyer a un espai de noms determinat. En el nostre codi d'exemple inicial tenim el següent codi XML
<?xml version="1.0" encoding="UTF-8" ?>
<menu
xmlns:d="http://www.mynamespace.org/dish"
xmlns:i="http://www.mynamespace.org/ingredients" >
<starters>
<d:dish>
<d:name>Tomato soup</d:name>
<d:price>2.0</d:price>
<i:ingredients>
<i:name>tomato</i:name>
<i:name>onion</i:name>
<i:name>carrot</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</d:dish>
<d:dish>
<d:name>French onion soup</d:name>
<d:price>2.0</d:price>
<i:ingredients>
<i:name>onion</i:name>
<i:name>butter</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</d:dish>
</starters>
<main>
<!-- More dishes -->
</main>
<!-- More menu elements ... -->
</menu>
Totes les etiquetes excepte la de "menu", "starters" i "main" pertanyen a l'espai de nom que identifiquem amb "dish" o "ingredients". Les etiquetes "menu", "starters" i "main" les podem associar a un espai de noms per defecte, que podem identificar amb el nom de menu ( al ser l'espai de noms per defecte no utilitzem cap prefix ! )
<?xml version="1.0" encoding="UTF-8" ?>
<menu
xmlns="http://www.mynamespace.org/menu"
xmlns:d="http://www.mynamespace.org/dish"
xmlns:i="http://www.mynamespace.org/ingredients" >
<starters>
<d:dish>
<d:name>Tomato soup</d:name>
<d:price>2.0</d:price>
<i:ingredients>
<i:name>tomato</i:name>
<i:name>onion</i:name>
<i:name>carrot</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</d:dish>
<d:dish>
<d:name>French onion soup</d:name>
<d:price>2.0</d:price>
<i:ingredients>
<i:name>onion</i:name>
<i:name>butter</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</d:dish>
</starters>
<main>
<!-- More dishes -->
</main>
<!-- More menu elements ... -->
</menu>
Amb aquest canvi no hem millorat gaire la llegibilitat del nostre document XML: molts prefixos en moltes etiquetes. Una millor opció pot ser utilitzar com a espai de noms per defecte l'associat a dish. D'aquesta forma podem eliminar del document tots els prefixos "d:" de totes les etiquetes. Com que en XML només hi pot haver un espai de noms per defecte actiu, haurem d'associar un prefix a l'espai de noms associat a menu!
<?xml version="1.0" encoding="UTF-8" ?>
<m:menu
xmlns:m="http://www.mynamespace.org/menu"
xmlns="http://www.mynamespace.org/dish"
xmlns:i="http://www.mynamespace.org/ingredients" >
<m:starters>
<dish>
<name>Tomato soup</name>
<price>2.0</price>
<i:ingredients>
<i:name>tomato</i:name>
<i:name>onion</i:name>
<i:name>carrot</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</dish>
<dish>
<name>French onion soup</name>
<price>2.0</price>
<i:ingredients>
<i:name>onion</i:name>
<i:name>butter</i:name>
<!-- More ingredients ... -->
</i:ingredients>
</dish>
</m:starters>
<m:main>
<!-- More dishes -->
</m:main>
<!-- More menu elements ... -->
</m:menu>
Espai de noms per defecte aniuats
Donat que un espai de noms és vigent per a l'etiqueta on es defineix i els seus nodes descendents, podem utilitzar espais de nom per defecte en diferents etiquetes. Podem reconstruir el nostre codi XML de la següent manera:
<?xml version="1.0" encoding="UTF-8" ?>
<m:menu
xmlns:m="http://www.mynamespace.org/menu"
xmlns="http://www.mynamespace.org/dish" >
<!-- ESPAI DE NOMS PER DEFECTE : dish -->
<m:starters>
<dish>
<name>Tomato soup</name>
<price>2.0</price>
<!-- CANVIEM ESPAI DE NOMS PER DEFECTE DE dish a ingredients -->
<ingredients xmlns="http://www.mynamespace.org/ingredients">
<name>tomato</name>
<name>onion</name>
<name>carrot</name>
<!-- More ingredients ... -->
</ingredients>
<!-- ESPAI DE NOMS PER DEFECTE : dish -->
</dish>
<dish>
<name>French onion soup</name>
<price>2.0</price>
<!-- CANVIEM ESPAI DE NOMS PER DEFECTE DE dish a ingredients -->
<ingredients xmlns="http://www.mynamespace.org/ingredients">
<name>onion</name>
<name>butter</name>
<!-- More ingredients ... -->
</ingredients>
</dish>
</m:starters>
<m:main>
<!-- More dishes -->
</m:main>
<!-- More menu elements ... -->
</m:menu>