Este apédice contiene varios algoritmos de espacio de nombre, como el algoritmo de normalización de espacio de nombre que fija la información de espacio de nombre en el Modelo de Objetos del Documento para producir un documento de espacio de nombre bien formado.
Si [XML 1.0] se usa (ver Document.xmlVersion
) los algoritmos se conforman para [Espacios de Nombres de XML], sino si [XML 1.1] se usa, los algoritmos conforman para [Espacios de Nombre de XML 1.1].
Las declaraciones de los atributos de Espacio de Nombre y prefijos son normalizadas como parte del método normalizeDocument
de la interfaz Document
como si el método descrito en el siguiente pseudo código fue llamado sobre el elemento documento.
void Element.normalizeNamespaces() { // Recoje las declaraciones locales de espacio de nombre // for ( todas las declarciones de atributos de espacio de nombre local de Element válidas en DOM Level 2 ) { if (la declaración del espacio de nombre no es válida) { // Nota: El prefijo xmlns es usado solamente para declarar vínculos y // por definición está enlazado al nombre del espacio de nombre http://www.w3.org/2000/xmlns/. // Esto no debe ser declarado. Ningún otro prefijo puede estar vinculado a este nombre de espacio // de nombre. ==> Reporta un error. } else { ==> Registra la declaración del espacio de nombre } } // Recoge el espacio de nombre del elemento // if ( namespaceURI del Element != null ) { if ( el par prefijo/espacio de nombre de Element (o el espacio de nombre predeterminado si no hay prefijo) están dentro del alcance de un vínculo ) { ==> No hace nada, la declaración al alcance es heredada Vea la sección "B.1.1: Alcance de un vínculo" para un ejemplo } else { ==> Crea una declaración attr de espacio de nombre local para este espacio de nombre, con el prefijo actual de Element (o un espacio de nombre predeterminado, si no hay prefijo). Si hay una declaración local contrapuesta a la ya puesta, se cambia su valor para usar este espacio de nombre. Vea la sección "B.1.2: Declaración de espacio de nombre contradictorios" para un ejemplo // Oberve que esto puede romper otros nodos en este subárbol de Element, // si estos están ya usando estos prefijos. // Estos serán reparados cuando sean alcanzados. } } else { // Element no tiene namespaceURI: if ( Nombre local de Element es null ) { // Nodo de DOM Nivel 1 ==> si un proceso de validación contra un esquema de espacio de nombre conocido (es decir Esquema XML) repora un error grave: el procesador no puede the processor recuperarse de esta situación. De otro modo, reporta un error: ningún espacio de nombre recuperado será representado sobre este nodo. } else { // Element no tiene pseudo-prefijo if ( hay un especio de nombre local predefinido contradictorio con el ya presente ) { ==> cambia su valor para usar este espacio de nombre vacío. } // Oberve que esto puede romper otros nodos en este subárbol de Element, // si estos están ya usando estos prefijos. // Estos serán reparados cuando sean alcanzados. } } // Examina y pule los atributos // for ( todos los Attrs sin espacio de nombre de Element ) { if ( Attr[i] tiene un namespaceURI ) { if ( atributo no tiene prefijo (espacio de nombre por defecto declarado no se puede aplicar a los atributos) O el prefijo del atributo no es declarado O conflicto: el atributo tiene un prefijo en conflicto con un vículo ya activo al alcance ) { if ( namespaceURI emparejado con una declaración de alcance de uno o más prefijos) { // escoje el vículo más local disponible; // si hay más de uno escoje uno aleatoriamente ==> cambia el prefijo del atributo. } else { if (el prefijo actual no es null y no tiene declaración de alcance) { ==> declara este prefijo } else { // encuentra el prefijo siguiendo el modelo "NS" +índice (empezando por 1) // asegurando que este prefijo no es declarado en el alcance actual. // crea un atributo de declaració de espacio de nombre local ==> cambia el prefijo del atributo. } } } } else { // Attr[i] no tiene namespaceURI if ( Attr[i] no tiene Nombre local ) { // Nodo de DOM Nivel 1 ==> si el proceso de validación contra un esquema de espacio de nombre conocido (es decir Esquema XML) reporta un error grave: el procesador no puede recuperarse de esta situación. De otro modo, reporta un error: ningún espacio de nombre recuperado será representado sobre este nodo. } else { // attr no tiene ningún namespaceURI ni prefijo // no se requiere ninguna acción, attrs no usa el predeterminado ==> no hace nada } } } // fin para todos los Attrs // hace esto recursivamente for ( todos los hijos elementos de Element ) { childElement.normalizeNamespaces() } } // fin de Element.normalizeNamespaces
Nota: Esta sección es informativa.
Un par prefijo/namespaceURI de un elemento se dice que está en el alcance de una vinculación si su prefijo de espacio de nombre está limitado al mismo namespaceURI en la definición [in-scope namespaces] en el [Conjunto de Información en XML].
Como ejemplo, el siguiente documento es cargado en un árbol DOM:
<root> <parent xmlns:ns="http://www.example.org/ns1" xmlns:bar="http://www.example.org/ns2"> <ns:child1 xmlns:ns="http://www.example.org/ns2"/> </parent> </root>
En el caso del elemento child1
element, el prefijo de espacio de nombre y namespaceURI están dentro del alcance de la declaración de espacio de nombre apropiada dado que el prefijo de espacio de nombre ns
de child1
limita con http://www.example.org/ns2
.
Usando el método Node.appendChild
, un elemento
child2
es añadido como un hermano de child1
con el mismo prefijo de espacio de nombre y namespaceURI, es decir, "ns"
y "http://www.example.org/ns2"
respectivamente. A diferencia child1
que contiene la declaración de espacio de nombre apropiada en su atributo, el par prefijo/namespaceURI de child2
está dentro del alcance de la declaración de espacio de nombre de su padre, y el prefijo de espacio de nombre "ns"
está limitado por "http://www.example.org/ns1"
. El par prefijo/namespaceURI de child2
por lo tanto no está al alcance de una vinculación. En orden a poner estos en un alcance de una vinculación, el algoritmo de normalización de espacio de nombre creará un valor de atributo de declaración de espacio de nombre para unir el prefijo de espacio de nombre "ns"
al namespaceURI "http://www.example.org/ns2"
y atará a child2
. La representación XML del documento despues de terminar el algoritmo de normalización de espacio de nombre será:
<root> <parent xmlns:ns="http://www.example.org/ns1" xmlns:bar="http://www.example.org/ns2"> <ns:child1 xmlns:ns="http://www.example.org/ns2"/> <ns:child2 xmlns:ns="http://www.example.org/ns2"/> </parent> </root>
Para determinar si un elementos está dentro del alcance de una vinculación, uno pude invocar Node.lookupNamespaceURI
, usando su prefijo de espacio de nombre como parámetro, y compara el namespaceURI resultante con el URI deseado, o uno puede invocar
Node.isDefaultNamespaceURI
usando su namespaceURI si el elemento no tiene prefijo de espacio de nombre.
Nota: Esta sección es informativa.
Un conflicto de declaraci&ocute;n de espacio de nombre podría ocurrir sobre un elemento si un nodo Element
y un atributo de declaración de espacio de nombre usan el mismo prefijo pero trazan un mapa a dos URIs de espacio de nombre diferentes.
Como ejempo, el documento siguiente es cargado en un árbol DOM:
<root> <ns:child1 xmlns:ns="http://www.example.org/ns1"> <ns:child2/> </ns:child1> </root>
Usando el método Node.renameNode
, el namespaceURI del elemento child1
es renombrado desde "http://www.example.org/ns1"
a "http://www.example.org/ns2"
. El prefijo de espacio de nombre "ns"
es ahora mapeado a dos URIs de espacio de nombre diferentes al nivel del elemento child1
y así la declaración del espacio de nombre es declarada contradictoriamente. El algoritmo de normalización de espacio de nombre resolverá el conflicto del prefijo de espacio de nombre modificando el valor de la declaración de espacio de nombre desde "http://www.example.org/ns1"
a "http://www.example.org/ns2"
. El algoritmo entonces continuará y considerará al elemento child2
, no encontrarán un mapa de declaración de espacio de nombre del prefijo de espacio de nombre "ns"
a "http://www.example.org/ns1"
en el alcance del elemento, y creará uno nuevo. La representación XML del documento despues de terminar el algoritmo de normalización de espacio de nombre será:
<root> <ns:child1 xmlns:ns="http://www.example.org/ns2"> <ns:child2 xmlns:ns="http://www.example.org/ns1"/> </ns:child1> </root>
Lo siguiente describe en pseudo código el algoritmo usado en el método lookupPrefix
de la interfaz Node
. Antes de devolver el prefijo encontrado el algoritmo necesita asegurarse de que el prefijo no está referido a un elemento del que comenzó la consulta. Estos métodos ignoran los nodos DOM Nivel 1.
Nota:
Este método ignora todas las declaraciones de espacio de nombre predeterminadas. Para encontrar el espacio de nombre predeterminado usa el método isDefaultNamespace
.
DOMString lookupPrefix(en DOMString de namespaceURI) { if (namespaceURI no tiene valor, es decir, el namespaceURI es null o cadena vacía) { return null; } short type = this.getNodeType(); switch (type) { case Node.ELEMENT_NODE: { return lookupNamespacePrefix(namespaceURI, this); } case Node.DOCUMENT_NODE: { return getDocumentElement().lookupNamespacePrefix(namespaceURI); } case Node.ENTITY_NODE : case Node.NOTATION_NODE: case Node.DOCUMENT_FRAGMENT_NODE: case Node.DOCUMENT_TYPE_NODE: return null; // type is unknown case Node.ATTRIBUTE_NODE: { if ( Attr tiene un Element propio ) { return ownerElement.lookupNamespacePrefix(namespaceURI); } return null; } default: { if (Node tiene un ascendente Element ) // EntityReferences deberín ser saltadas para conseguirlo { return ancestor.lookupNamespacePrefix(namespaceURI); } return null; } } } DOMString lookupNamespacePrefix(DOMString namespaceURI, Element originalElement){ if ( Element tiene un espacio de nombre y un espacio de nombre de Element == namespaceURI y Element tiene un prefijo y originalElement.lookupNamespaceURI(prefijo de Element) == namespaceURI) { return (el prefijo de Element); } if ( Element tiene atributos) { for ( todos los atributos de declaraci&ocute;n de espacio de nombre local válidos en DOM Nivel 2 de Element ) { if (prefijos de Attr == "xmlns" y valor de Attr == namespaceURI y originalElement.lookupNamespaceURI(nombre local de Attr) == namespaceURI) { return (nombre local de Attr); } } } if (Node tiene un ascendente Element ) // EntityReferences deberín ser saltadas para conseguirlo { return ancestor.lookupNamespacePrefix(namespaceURI, originalElement); } return null; }
Lo siguiente describe en pseudo código el algoritmo usado en el método isDefaultNamespace
de la interfaz Node
. Este método ignora los nodos de DOM Nivel 1.
boolean isDefaultNamespace(in DOMString namespaceURI) { switch (nodeType) { case ELEMENT_NODE: if ( Element no tiene prefijo ) { return (espacio de nombre de Element == namespaceURI); } if ( Element tiene atributos y hay una declaración de espacio de nombre predeterminada válida en DOM Nivel 2, es decir, el Nombre local de Attr == "xmlns" ) { return (valor de Attr == namespaceURI); } if ( Element tiene un ascendente Element ) // EntityReferences deberín ser saltadas para conseguirlo { return ancestorElement.isDefaultNamespace(namespaceURI); } else { return unknown (false); } case DOCUMENT_NODE: return documentElement.isDefaultNamespace(namespaceURI); case ENTITY_NODE: case NOTATION_NODE: case DOCUMENT_TYPE_NODE: case DOCUMENT_FRAGMENT_NODE: return unknown (false); case ATTRIBUTE_NODE: if ( Attr tiene un Element propio ) { return ownerElement.isDefaultNamespace(namespaceURI); } else { return unknown (false); } default: if ( Node has an ancestor Element ) // EntityReferences deberín ser saltadas para conseguirlo { return ancestorElement.isDefaultNamespace(namespaceURI); } else { return unknown (false); } } }
Lo siguiente describe en pseudo código el algoritmo usado en el método lookupNamespaceURI
de la interfaz Node
. Estos métodos ignoran los nodos del DOM Nivel 1.
DOMString lookupNamespaceURI(in DOMString prefix) { switch (nodeType) { case ELEMENT_NODE: { if ( espacio de nombre de Element != null y prefijo de Element == prefix ) { // Nota: el prefijo podría ser "null" en este caso se buscaría el espacio de nombre predeterminado return (espacio de nombre de Element); } if ( Element tiene atributos) { for ( todos los atributos de declaración de espacio de nombre local válidos en DOM Nivel 2 de Element ) { if (prefijo de Attr == "xmlns" y localName de Attr == prefix ) // no espacio de nombre predeterminado { if (valor de Attr es no vacío) { return (valor de Attr); } return unknown (null); } else if (nombre local de Attr == "xmlns" y prefijo == null) // espacio de nombre predeterminado { if (valor de Attr no es vacío) { return (valor de Attr); } return unknown (null); } } } if ( Element tiene un ascendente Element ) // EntityReferences deberín ser saltadas para conseguirlo { return ancestorElement.lookupNamespaceURI(prefix); } return null; } case DOCUMENT_NODE: return documentElement.lookupNamespaceURI(prefix) case ENTITY_NODE: case NOTATION_NODE: case DOCUMENT_TYPE_NODE: case DOCUMENT_FRAGMENT_NODE: return unknown (null); case ATTRIBUTE_NODE: if (Attr tiene un Element propio) { return ownerElement.lookupNamespaceURI(prefix); } else { return unknown (null); } default: if (Node has an ancestor Element) // EntityReferences deberín ser saltadas para conseguirlo { return ancestorElement.lookupNamespaceURI(prefix); } else { return unknown (null); } } }