Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found in GNU Free Documentation License.
La libreria Gnome DOM o simplemente gdome fue escrita principalmente por:
Paolo Casarini [Department of Computer Science, University of Bologna] Luca Padovani [Department of Computer Science, University of Bologna]
Citando a la página de W3C (World Wide Web Consortium) sobre DOM (Document Object Model)
El Modelo de Objetos para Documentos (MOD) es una plataforma e interfaz independiente del lenguaje que permitirá a los programas y scripts acceder y actualizar el contenido, la estructura y estilo de los documentos.
Más concretamente, la espeficación del modelo DOM nivel2 define una jerarquía de interfaces proporcionando una API (Interfaz para la programación de aplicaciones) orientada a objetos para navegar y operar en un documento HTML (Lenguaje de marcas de hipertexto) o bien, documentos XML (Lenguaje de Marcas eXtensible).
Las interfaces son proporcionadas por la gestión de los elementos, atributos, nodos de texto, así como los otros tipos nodo XML. Cuando se habla de estas entidades en general, nosotros las llamaremos nodos 'document'. De hecho, node (nodo) es una de las interfaces DOM fundamentales de las cuales las otras entidades derivan. Las operaciones básicas de los nodos incluyen la creación, el borrado y recuperación. A través de esto, la especificación DOM incluso proporciona un conjunto de interfaces para la implementación de aplicaciones controladas por eventos. Los eventos pueden ser activados por acciones del usuario (tales como eventos GUI(Interfaz gráfica de usuario)) o por modificaciones de la estructura de los documentos y su contenido.
Una implementación DOM (también llamada una implementación host) es una parte de software que implementa todas (o un subconjunto de ellas) las interfaces definidas en la especificación DOM. En una visión más sencilla, toma un documento XML interpretado y lo hace disponible para su procesamiento a través de la implementación de un lenguaje. Pero otro aspecto fundamental de la arquitectura DOM es que DOM proporciona unicamente la interfaz mínima, y que cada aplicación puede implementar más clases específicas derivadas de las básicas.
El motor DOM de GNOME (en breve, Gdome2 (motor Gnome DOM), mira http://www.cs.unibo.it/~casarini/gdome2/) es una implementación DOM cuyo objetivo es el de proporcionar una interfaz a los documentos XML a los programadores que es:
* Eficiente * Fácil de usar * Cumple los estandards de W3C
Basicamente, el problema es que en las implementaciones de DOM hay una considerable sobrecarga, las aplicaciones están obligadas a utilizar una interfaz que sea capaz de modificar y acceder su estado. Además, hay también requerimientos para el almacenamiento del propio estado.
Por lo tanto, nuesto primer objetivo es hacer de DOM una interfaz atractiva para las aplicaciones de GNOME, para almacenar su estado, configuración, información y demás. Además, como nosotros también investigamos la posibilidad de proporcionar un entorno unificado permitiendo la unión de componentes dentro de una misma aplicación, cada componente destinado a gestionar un determinado subconjuto de marcas dentro de un documento XML (normalmente, las marcas siguen una determinada nomenclatura, esto es la conocida arquitectura de documentos centralizada de las aplicaciones, donde la estructura central es dada por el documento y los componentes son conectados según se vayan necesitando.
Gdome2, cuyo objetivo es el de seguir estas funciones, actualmente soporta los módulos Core y XML definidos en la especificación de DOM nivel 2, pero se supone que se llegará a conseguir una completa implementación de todo las interfaces de DOM. Sin embargo, la mayoría del diseño se dedice en esta fase, debido a que la mayoría de los otros módulos y niveles están incorporados por encima de la interfaz core.
En esta sección nosotros daremos una visión general a parte de la API implementada en Gdome2, en particular la que no es estandar. Nosotros también veremos el cuerpo de un programa sencillo basado en Gdome2.
En Gdome2, los atributos y los métodos descritos en las interfaces de DOM nivel2 están implementadas como funciones en C. En el resto del articulo, nosotros usaremos el término método para denotar la función en C implementando el método DOM.
Cada interface DOM tiene un tipo correspondiente en C cuyo nombre es el nombre de la propia interfaz DOM con un prefijo Gdome. Por ejemplo, GdomeNode es el tipo correspondiente a la interfaz Node DOM.
Todos los nombres de las funciones API comienzan con la cadena gdome_ (identificador que se refiere a la nomenclatura de la libreria Gdome2) seguido de un prefijo abreviado que indica la interfaz DOM a la que el método se refiere. En la siguiente tabla damos la completa correspondencia entre la interfaz DOM y los prefijos Gdome2.
Gdome2 Prefixes DOM Interface Gdome2 Prefix DOMImplementation di_ DocumentFragment df_ Document doc_ Node n_ NodeList nl_ NamedNodeMap nnm_ CharacterData cd_ Attr a_ Element el_ Text t_ Comment c_ CDATASection cds_ DocumentType dt_ Notation not_ Entity ent_ EntityReference er_ ProcessingInstruction pi_
Entonces, los cambios de la sintaxis dependen del tipo de acceso al método o atributo implementado por la función. Los métodos explícitos son proporcionados a través de la lectura y escritura de los valores de los atributos (el acceso de escritura a atributos de sólo lectura es simplemente prevenido por la carencia del correspondiente método de escritura).
la sintaxis de las funciones de la API de Gdome2 se resume abajo, donde DOMMethodName y DOMAttrName son interfaces donde se guardan, respectivamente, los métodos de la interfaz y los atributos de la interfaz en la especificación DOM.
Gdome2Method ::= 'gdome_' InterfacePrefix DOMMethodName Gdome2SetAttr ::= 'gdome_' InterfacePrefix 'set_' DOMAttrName Gdome2GetAttr ::= 'gdome_' InterfacePrefix DOMAttrName
Todas las funciones implementadas de Gdome2 por la API DOM tienen dos parametros añadidos en comparación con la especificación DOM: el primer parámetro es siempre una referencia al objeto del cual estamos invocando el método. Este parámetro está normalmente implícito en los lenguajes orientados a objetos donde se referencia con self o this. El ultimo parámetro es siempre una referencia a una estructura GdomeException utilizada para guardar la posible excepción lanzada por la invocación del método (nosotros volveremos a llamarlo ya que el lenguaje de programación C no tiene un mecanismo nativo para el manejo de excepciones). Todos los otros parámetros están en una correspondencia uno-a-uno con los parametros especificados por la interfaz DOM.
Según el ejemplo, el método appendChild de la interfaz Node está implementado en Gdome2 por una función con el siguiente prototipo:
GdomeNode *gdome_n_appendChild (GdomeNode *self, GdomeNode *newChild, GdomeException *exc)
La implementación de DOMString merece su propia sección, ya que es el unico que difiere en algunos aspectos de la especificación DOM. De hecho, la especificación requiere que DOMString sea codificado usando UTF (Formato de Transformación UCS)-16 [Unicode]. mientras que Gdome2 utiliza una codificación UTF-8. Esto es debido a que Gdome2 actua como un wrapper de otra libreria que interpreta documentos XML, libxml2, que ya adopta internamente la codificación UTF-8.
Algunos de los motivos de este cambio son los siguientes (ver [codificación] para un tratamiento más a fondo de este tema referente a libxml2):
*UTF-8, aunque es un poco más complejo de convertir desde/a con respecto a UTF-16, es también más compacto en la mayoría de los documentos.
UTF-8 se está utilizado como un tipo de codificación estandar en los widgets de texto de GNOME y en una gran cantidad de código de Unix Linux.
En practica, el GdomeString es una sencilla estructura compuesta de un campo str, que es un puntero a una secuencia de bytes ensamblados, como una cadena UTF-8 válida. Así que los usuarios de Gdome2 sólo necesitan que el texto en plano ASCII (Código estandar americano para el intercambio de información), esté propiamente convertido a UTF-8.
En un futuro cercano, planeamos añadir nuevos métodos de acceso y conversión, teniendo en cuenta otras codificaciones como la UTF-16.
Para gestionar la asignación de objetos GdomeDOMString, Gdome2 tiene tres diferentes constructores, dependiendo de la clase de asignación de espacio de la cadena fuente utilizada como inicializador:
GdomeDOMString *gdome_str_mkref(const gchar* str) GdomeDOMString *gdome_str_mkref_own(gchar* str) GdomeDOMString *gdome_str_mkref_dup(const gchar* str)
gdome_str_mkref crea una GdomeDOMString desde una cadena asignada estaticamente. gdome_str_mkref_own debe de ser utilizada cuuando el usuario quiere hacer una GdomeDOMString, desde un buffer gchar asignado dinamicamente. El buffer se liberará automaticamente cuando se destruya el objeto. Finalmente, gdome_str_mkref_dup es similar a la anterior, pero se hace una copia de la cadena inicializada antes de su construcción.
Para liberar una GdomeDOMString, sólo se utiliza su destructor gdome_str_unref.
El primer paso para que cualquier aplicación utilize Gdome2 es la creación de una instancia del objeto DOMImplementation, que proporciona un número de métodos para la realización de operaciones independientemente de cualquier determinada instancia del modelo de objetos para documentos tales como la creación de un nuevo objeto Document o DocumentType.
Dentro de la especificación DOM, la única manera de crear un objeto Document es por medio del método createDocument en la interfaz DOMImplementation.
En Gdome2 esta característica está implementada por:
GdomeDocument* gdome_di_createDocument (GdomeDOMImplementation *self, GdomeDOMString *namespaceURI, GdomeDOMString *qualifiedName, GdomeDocumentType *doctype, GdomeException *exc)
que crea un objeto Document del tipo especificado con un elemento raíz especificado por namespaceURI y qualitifiedName.
Gdome2 también implementa una forma no-estandar de crear un nuevo objeto Document interpretando un documento XML identificado por una URI (Identificador de Recursos Unifrome):
GdomeDocument* gdome_di_parseFile (GdomeDOMImplementation *self, const gchar* uri, GdomeException* exc)
El documento puede también ser validado utilizando gdome_DOMImplementation_validateFile que tiene el mismo prototipo que el método de arriba.
Para mostrar alguna de las funcionalidades más comunes de Gdome2 presentamos un sencillo ejemplo que resuelve una frecuente tarea, que es la de quitar los comentarios y nodos en blanco de un árbol DOM. Esto puede ser útil, para obligar que no haya variaciones en las posiciones de los nodos dentro de un documento validado
int main (int argc, char **argv) { GdomeDOMImplementation *domimpl; GdomeDocument *domdoc; GdomeElement *rootel; GdomeException exc; domimpl = gdome_di_mkref(); domdoc = gdome_di_parseFile (domimpl, argv[1], ); rootel = gdome_doc_documentElement (domdoc, ); cleanSubTree ((GdomeNode *)rootel); gdome_di_saveFile (domimpl, "out.xml", domdoc, ); gdome_di_freeDoc (domimpl, domdoc, ); return 0; }
Primero de todo, el usuario Gdome2 tiene que arrancar la libreria y cargar el archivo de datos XML en un objeto GdomeDocument. Entonces, recupera la referencia al GdomElement raíz del documento por medio del método gdome_doc_documentElement.
En este punto, llama a la función cleanSubTree y finaliza guardando el resultado del documento en el sistema de ficheros.
Vamos ahora a prestar nuestra atención en la función cleansubtree, descrita abajo:
void cleanSubTree (GdomeNode *node) { GdomeNodeList *nl; GdomeException exc; GdomeNode *child; long i, nllength; nl = gdome_n_childNodes (node, ); if ((nllength = gdome_nl_length (nl, )) == 0) return; for (i = nllength - 1 ; i >= 0; i--) { child = gdome_nl_item(nl, i, ); if (gdome_n_nodeType (child, ) == GDOME_COMMENT_NODE || (gdome_n_nodeType (child, ) == GDOME_TEXT_NODE && isSpaceStr (gdome_t_data ((GdomeText *)child, )))) gdome_n_removeChild (node, child, ); else if (gdome_n_hasChildNodes (child, )) cleanSubTree (child); } }
Primero, recuperamos la estructura NodeList con la lista de los hijos del nodo actual. Siguiente, nosotros tenemos que iterar en cada nodo, posiblemente quitando el nodo en caso de ser un comentario o un nodo en blanco
Ahora queremos explotar la propiedad "vitalidad" de la estructura Nodelist donde los cambios al árbol son automaticamente reflejados en la lista. Sin embargo, esto es un problema si uno va a acceder a a la lista por medio de un índice progresivo, debido a que como los nodos son borrados de la lista llegan a ser más pequeños y el conjunto de índices válidos más pequeños. Por esta razón, nosotros desarrollamos la función como un bucle donde el índice decrementa en cada iteración. De esta forma, nosotros siempre accedemos al nodo adecuado, tanto si ha sido borrado el previo nodo o sino se ha borrado.
En el resto, los hijos son recursamente visitados según son encontrados.
Una de las primeras cuestiones que se tuvieron en cuenta cuando la implementación de DOM en un lenguaje imperativo como C fue el que fuese DOM una arquitectura orientada a objetos.
Los objetos Gdome2 se implementados de una forma no ambigua. los objetos tienen campos clasificados en campos instancia y campos clase. Los campos instancia son asignados por cada instancia de una clase dada (donde la 'clase' es la realización de una interfaz DOM), y estos están agrupados en una estructura estandar en C. Los campos clase son campos compartidos por todas las instancias de una interfaz dada. Cada objeto Gdome2 tiene un campo instancia que es un puntero a una estructura asignada estaticamente que contiene sus campos clase.
Un ejemplo típico de una clase campo que está presente en todos los objetos de Gdome2 es la 'tabla virtual o virtual table', que contiene punteros a los métodos implementados por la propia clase objeto.
La importancia de tablas virtuales es doble: primero, el verdadero motivo es que permite un mecanismo equivalente a la 'herencia' de métodos, por lo que favorece volver a usar el código y por ultimo, hacer más fácil el mantenimiento del código fuente. Pero, más importante, las tablas virtuales se necesitan para tener late-binding, que es una característica común de los lenguajes orientados a objetos que permite retrasar la elección del método a ser llamado sobre un objeto hasta que se conoce el tipo de objeto en tiempo de ejecución.
Aunque la arquitectura del modelo DOM puede utilizarse para la creación de nuevos documentos que no están ubicados en una referencia externa, una implementación DOM no es tipicamente sólo un trozo de software: en la mayoría de los casos, se le añade una especie de capa de separación entre el intérprete XML y las aplicaciones del usuario.
La distinción entre el intérprete y la implementación DOM no está siempre tan definida. Por ejemplo, una implementación DOM puede proporcionar su propio módulo intérprete, así que la capa DOM aparece como la más baja desde el punto de vista de la aplicación. Alternativamente, el intérprete XML podría solo ser responsable de generar una determinada secuencia de eventos SAX (Simple API for XML), y luego la implementación DOM de crear la representación interna del documento.
Según veremos, la aproximación utilizada en Gdome2 es algo como un hilo de los dos escenarios previamente relatados. De hecho, Gdome2 está basado en la libreria XML de C para Gnome (libxml en breve) que es mucho más que un mero intérprete XML. Con respecto al interprete, libxml2 exporta tres tipos de interfaces:
* Una interfaz de eventos SAX
* Un método Pull, que interpreta un documento entero y devuelve la correspondiente estructura del documento.
* Un método Push, donde el documento se interpreta por demanda, según la aplicacion requiera más partes sean interpretadas. Este método tiende a ser usado, por ejemplo, en aplicaciones interactivas donde no es factible bloquear el proceso entero mientras se interpreta un documento largo.
En particular, los ultimos dos métodos incorporan una representación del árbol del documento dependiente de libxml2 que no está dada en la espcificación core de DOM, y esto es un aspecto vital de toda implementación de Gdome2 como veremos luego.
Desde el punto de vista de DOM, los documentos tienen una estructura lógica que es muy parecida a la de un árbol; para ser más preciso, que es como un 'bosque' o 'bosquecillo' ya que nosotros podemos trabajar con varios árboles de documentos a la misma vez. La especificación DOM es extensamente organizada entorno a una interfaz Node, que es la base de lo que están hechos los árboles y los que definen los métodos básicos para el recorrido del documento (tales como recorrer el padre de un nodo, su primer hijo, el siguiente hermano y así en adelante). Más formalmente, el árbol DOM está hecho de entidades que implementan la interfaz Node.
Como hemos visto, libxml2 tiene su propio concepto de árbol de documentos. Así, desde una parte de libxml2 es un trabajo ya hecho en la implementación DOM que es relativamente ligera y está más aún justificado por el hecho de que permite la validación de documentos. Desde la otra cara, no es definitivamente una implementación DOM, no exporta una completa interfaz DOM y es algo como dirigido al uso interno de libxml2 del documento
De este modo, Gdome2 actúa como un wrapper de la estructura en árbol de libxml2, implementando de una forma uniforme las interfaces DOM y ocultando finalmente cualquier detalle relevante de la estructura interna de libxml2. Un node Gdome2 es sólo un wrapper con una referencia al nodo actual de libxml2. Además, como nosotros veremos, los nodos wrappers de Gdome2 son guardados en caché, por lo que sólo un wrapper puede asignarse por un nodo dado del árbol, indiferentemente del número real de referencias de la aplicación del usuario a ese nodo.
Esta aproximación tiene la ventaja de que coge la mayoría de la estructura interna de libxml2 para la implementación de DOM, con el mínimo código dulplicado y que es ligero en cuanto a uso de memoria: los wrappers node de Gdome2 son unicamente usados para almacenar campos y proporcionar funcionalidades no disponibles directamente unicamente por medio de los nodos libxml2.
La implementación de Gdome2 de la interfaz node consiste de un conjunto de funciones que proporcionan:
Acesso de lectura para los atributos de sólo lectura
Acceso de lectura/escritura para modificar los atributos del nodo por medio de un par de funciones get/set;
La semantica asociada al correspondiente método en la especificación DOM
En particular, la ultima posibilidad es, o hacer una implementacon sencilla que apunte al método de la correspondiente función libxml2 sobre el nodo libxml2, si tal función está ya implementada en libxml2, o implementarla en el caso de que falte.
Como nosotros ya apuntamos en la anterior sección, la estructura en árbol de libxml2 no es siempre suficiente (no la adecuada, en algunos casos) para completamente implementar la especificación DOM.
Cada vez que la aplicación del usuario pide la primera vez manejar un nodo determinado del documento, Gdome2 crea una estructura wrapper con una referencia interna al correspondiente nodo libxml2. Los elementos, atributos y, en general, todas las entidades derivadas de Node comparten la misma estructura que los nodos genericos; el mecanismo de herencia implementado en Gdome2 permite la compartición de métodos comunes. En este punto, Gdome2 devuelve un puntero 'opaco' a la estructura GdomeNode de este modo preveniendo cualquier modificicación peligrosa de los campos internos utilizados por gdome2.
La estructura interna de un nodo es la siguiente:
typedef struct _Gdome_xml_Node Gdome_xml_Node; struct _Gdome_xml_Node { GdomeNode super; int refcnt; xmlNode *n; GdomeAccessType accessType; Gdome_xml_ListenerList *ll };
Gdome2 utiliza un mecanismo de contador de referencias para guardar el número de usuarios (o referencias de vida) de un nodo dado: se comparte la estructura por todos los usuarios que piden el mismo Nodo DOM, y la estructura es ocasionalmente liberada tan pronto como el contador alcanza 0.
La compartición de esta estructura se implementa a través del campo field en los nodos libxml2; cuando un nodo de Gdome2 es solicitado por un usuario, primero se comprueba en en el campo _private del nodo correspondiente de libxml2. Si este campo es NULL, entonces se accede al nodo por primera vez, Gdome2 asigna e inicializa una nueva estructura wrapper y fija un puntero al campo _private. Por otra parte, si _private no es un puntero a NULL, entonces Gdome2 asume que está previamente asignado Gdome_xml_Node y simplemente devuelve su valor, teniendo que incrementar el contador de referencia.
Sin embargo, hay dos casos donde las estructuras de libxml2 no son adecuados para este tipo de manejo:
DocumentType
Siguiendo la especicificación de DOM, este nodo está hecho para proporcionar listas de entidades y anotaciones que son declaradas tanto en el DTD (declaración del tipo de documento) extero e interno del documento. Sin embargo, libxml2 incorpora diferentes tablas hash depediendo de si las entidades o anotaciones vienen de un fragmento interno o externo del DTD, con un total de 4 diferentes tablas hash. Por lo que cuando un manejador al nodo DocumentType es solicitado, Gdome2 incorpora dos nuevos tipos de tablas hash, uno para las entidaes y otro para las anotaciones.
Anotación
Por razones históricas, en libxml2 este nodo tiene una estructura determinada y muy sencilla. Por lo que el manejo de este nodo es igual que con los otros tipos de nodos (en particular con el de la implementación de la interfaz DocumentType), Gdome2 asigna un wrapper al nodo anotación de libxml2, por lo que se parece a todos los otros nodos.
Una de las más importantes interfaces de la especificación Core de DOM es la interfaz NodeList, que se utiliza para manejar listas ordenadas de Nodos tales como los hijos de un nodo, o los elementos devueltos por el método getElementByTagName de la interfaz Elemento. Similarmente, hay también una interfaz NameNodeMap utiliza para el manejo de conjuntos de nodos no-ordenados referenciados por los atributos del nombre, tales como los atributos de un Element. Una de sus principales características es que son como estructuras 'vivas', eso eso, los cambios de la estructura del documento son automaticamente reflejadas en toda la NodeList y NamedNodeMap. Por ejemplo, si un usuario de DOM obtiene un objeto NodeList que contiene el hijo de un Element, y el posteriormente añade más hijos a ese elemento, entonces los hijos añadidos son simultaneamente añadidos a la NodeList, sin que el usuario haya hecho nada. Por supuesto, los cambios a un nodo de un árbol se reflejan en todas las referencias a ese nodo en los objetos NodeList y NamedNodeMap.
La interfaz NodeList proporciona la abstracción de una colección de nodos ordenados.
Una primera forma de implementar la interfaz NodeList es físicamente representarla como una lista de manejadores de nodos. Para que parezca estar viviva, nosotros podríamos tener una lista creada de las listas NodeList activas asociadas al documento o a los objetos DOMImplementation que son dueños de esos nodos. Entonces, cualquier función que modifique de alguna manera la estructura del árbol tiene que actualizar todas las listas donde los nodos modificados aparezcan. Esta implementaciónt tiene la gran ventaja de ser una lista, de modo que el recorrido y la búsqueda puedan ser realizadas rapidamente (en particular, el método getElementsByTagName). Sin embargo, la contabilidad requerida para mantener las listas no es factible, especialmente si el documento va a modificarse.
La forma alternativa, que está implementada en Gdome2, intenta redudir el tamaño en memoria ocupado utilizando una estructura upoco concisa. Mas especificamente, cuando se solicita un NodeList, nosotros devolvemos una referencia a la siguiente estructura:
typedef struct _Gdome_xml_NodeList Gdome_xml_NodeList; struct _Gdome_xml_NodeList { GdomeNodeList super; int refcnt; GdomeNode *root; GdomeDOMString *tagName; GdomeDOMString *tagURI; GdomeAccessType accessType; };
Entre los campos de esta estructura tenemos una referencia a la estructura GdomeNode llamada root apuntado a la raíz del subárbol (cada NodeList es parte de un determinado subárbol, por razones de eficiencia. En el peor caso, root es el nodo del documento que más arriba está, correspondiente al árbol entero). tagName es una referencia a GdomeDOMString que es un nombre local o calificado a ser marcado, cuando el campo no es NULL, la lista incluye cualquier elemento con nombre dado que es un descendiente del elemento raíz dado. Por otra parte, cuando el campo es NULL, la lista sólo incluye los nodos hijo del elemento raíz. tagURI es una referencia a un GdomeDOMString que representa el espacio de nombres de una URI. Al igual que en el anterior campo, puede ser NULL para las listas que contengan nodos indistintamente al espacio de nombres.
Fijaté que ninguna otra estructura dentro de Gdome_xml_Nodelist está asignada, cuando el usuario llama a los métodos de la interfaz NodeList simplemente recorremos el árbol DOM empezando por el nodo raíz, posiblemente aplicando el filtro representado por el tagName y tagURI, en caso de que se especifique. En este sentido, la implementación de un NodeList es parecido a un filtro de vida en el árbol DOM.
Desafortunadamente, es relativamente complejo encontrar alguna optimización efectiva para esta estructura, debido a su propiedad de "tiempo de vida" ya que, en general, el tiempo de acceso es linear a la longitud de la lista. Esto podría hacer que se introduzcan algunas interfaces no estandards para una recuperación más eficiente de los nodos del documento en un futuro cercano.
Sin embargo, fijaté que cada lista nodo en la que el nodo raíz está definido sólo como lectura una vez y para todo en el momento de su creación, las optimizaciones pueden ser hechas. En particular, el tiempo de acceso puede reducirse desde linear a constante en el cado de una lista de nodos no filtrada.
La implementación de los objetos de la interfaz NamedNodeMap se utilizan para representar colecciones de nodos que pueden accederse por el nombre,
[C] B.W.Kernighan, D.M.Ritchie, ``The C Programming Language'', Second Edition, Prentice Hall, June 1988.
[CPP] B.Stroustrup, ``The C++ Programming Language'', Special Edition, Addison-Wesley, February 15, 2000.
[DOM] ``Document Object Model (DOM) Level 2 Specification''. Version 1.0, W3C Recommendation, 13 November 2000.
http://www.w3.org/TR/2000/CR-DOM-Level-Core/
http://www.w3.org/TR/DOM-Level-2-Events/
http://www.w3.org/TR/DOM-Level-2-Traversal-Range/
[encoding] D.Veillard, ``Libxml Internationalization Support'', http://xmlsoft.org/encoding.html
[HUN00] D.Hunter et al., ``Beginning XML'', Wrox Press Inc., June 2000.
[Java] K.Arnold, J.Gosling, D.Holmes, ``The Java Programming Language'', Third Edition, Addison-Wesley, June 15, 2000.
[LEVDOM99] R.Levien, ``Gnome World DOMination'', 14 April 1999, http://www.levien.com/gnome/domination.html
[LEVPA99] R.Levien, ``Pango Proposal'', rev 0.1, July 28, 1999, http://www.levien.com/gnome/pango-0.1.html
[LEVTXT99] R.Levien, ``Gnome-Text API Documentation'', July 10, 1999, http://www.levien.com/gnome/gnome-text.html
[Names99] ``Namespaces in XML'', W3C Recommendation, January 14, 1999, http://www.w3.org/TR/1999/REC-xml-names-19990114/
[Unicode] The Unicode Consortium, ``The Unicode Standard'', version 3.0, Frebruary 2000, http://www.unicode.org/unicode/standard/versions/Unicode3.0.html
[UTF-8] F.Yergeau, ``UTF-8, a transformation format of ISO 10646'', IETF (Internet Engineering Task Force), RFC 2279, http://www.ietf.org/rfc/rfc2279.txt
[Xerces] ``Xerces-C++ Parser'', Version 1.4.0, http://xml.apache.org
[XML00] ``Extensible Markup Language (XML) 1.0'', Second Edition, W3C Recommendation, 6 October 2000, http://www.w3.org/TR/2000/REC-xml-20001006
Paolo Casarini [Department of Computer Science, University of Bologna: casarini@cs.unibo.it]
Luca Padovani [Department of Computer Science, University of Bologna: luca.padovani@cs.unibo.it]