| You are here: Inicio > Inmersión en Python > Scripts y flujos > Caché de búsqueda de nodos | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
kgp.py emplea varios trucos que pueden o no serle útiles en el procesamiento de XML. El primero aprovecha la estructura consistente de los documentos de entrada para construir una caché de nodos.
Un fichero de gramática define una serie de elementos ref. Cada ref contiene uno o más elementos p, que pueden contener un montón de cosas diferentes, incluyendo xrefs. Cada vez que encuentras un xref, se busca el elemento ref correspondiente con el mismo atributo id, se escoge uno de los hijos del elemento ref y se analiza (veremos cómo se hace esta elección al azar en la siguiente sección).
Así es como se construye la gramática: definimos elementos ref para las partes más pequeñas, luego elementos ref que "incluyen" el primer elemento ref usando xref, etc.. Entonces se analiza la referencia "más grande" y se sigue cada xref hasta sacar texto real. El texto de la salida depende de las decisiones (al azar) que se tomen cada vez que seguimos un xref, así que la salida es diferente cada vez.
Todo esto es muy flexible, pero hay un inconveniente: el rendimiento. Cuando se encuentra un xref y necesitamos encontrar el elemento ref correspondiente, tenemos un problema. El xref tiene un atributo id, y queremos encontrar el elemento xref que tiene el mismo atributo id pero no hay manera sencilla de acceder a él. La manera lenta sería obtener la lista completa de elementos ref cada vez, y luego iterar manualmente mirando el atributo id de cada uno. La manera rápida es hacer eso una vez y construir una caché en un diccionario.
def loadGrammar(self, grammar):
self.grammar = self._load(grammar)
self.refs = {}
for ref in self.grammar.getElementsByTagName("ref"):
self.refs[ref.attributes["id"].value] = ref

| Empiece creando un diccionario vacío, self.refs. | |
| Como vio en Sección 9.5, “Búsqueda de elementos”, getElementsByTagName devuelve una lista de todos los elementos con un nombre en particular. Podemos obtener fácilmente una lista de todos los elementos ref y luego iterar sobre esa lista. | |
| Como vio en Sección 9.6, “Acceso a atributos de elementos”, podemos acceder a atributos individuales de un elemento por su nombre, usando la sintaxis estándar de un diccionario. Así que las claves del diccionario self.refs serán los valores del atributo id de cada elemento ref. | |
| Los valores del diccionario self.refs serán los elemento ref en sí. Como vio en Sección 9.3, “Análisis de XML”, cada elemento, cada nodo, cada comentario, cada porción de texto de un documento XML analizado es un objeto. |
Una vez construya esta caché, cada vez que encuentre un xref y necesite buscar el elemento xref con el mismo atributo id, simplemente puede buscarlo en self.refs.
def do_xref(self, node):
id = node.attributes["id"].value
self.parse(self.randomChildElement(self.refs[id]))Exploraremos la función randomChildElement en la siguiente sección.
<< Entrada, salida y error estándar |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
Encontrar hijos directos de un nodo >> |