"xml.etree.ElementTree" --- La API XML de ElementTree
*****************************************************

**Código fuente:** Lib/xml/etree/ElementTree.py

======================================================================

El módulo "xml.etree.ElementTree" implementa una API simple y
eficiente para parsear y crear datos XML.

Distinto en la versión 3.3: Este módulo utilizará una implementación
rápida siempre que esté disponible.

Obsoleto desde la versión 3.3: El módulo "xml.etree.cElementTree" es
obsoleto.

Advertencia:

  El módulo "xml.etree.ElementTree" no es seguro contra datos
  construidos maliciosamente. Si necesita parsear datos no fiables o
  no autentificados, vea Vulnerabilidades XML.


Tutorial
========

Este es un tutorial corto para usar "xml.etree.ElementTree" ("ET" en
resumen). El objetivo es demostrar algunos de los componentes y
conceptos básicos del módulo.


Árbol y elementos XML
---------------------

XML es un formato de datos inherentemente jerárquico, y la forma más
natural de representarlo es con un árbol. "ET" tiene dos clases para
este propósito - "ElementTree" representa todo el documento XML como
un árbol, y "Element" representa un solo nodo en este árbol. Las
interacciones con todo el documento (leer y escribir en/desde
archivos) se realizan normalmente en el nivel de "ElementTree". Las
interacciones con un solo elemento XML y sus sub-elementos se realizan
en el nivel "Element".


Procesando XML
--------------

Usaremos el siguiente documento XML como los datos de muestra para
esta sección:

   <?xml version="1.0"?>
   <data>
       <country name="Liechtenstein">
           <rank>1</rank>
           <year>2008</year>
           <gdppc>141100</gdppc>
           <neighbor name="Austria" direction="E"/>
           <neighbor name="Switzerland" direction="W"/>
       </country>
       <country name="Singapore">
           <rank>4</rank>
           <year>2011</year>
           <gdppc>59900</gdppc>
           <neighbor name="Malaysia" direction="N"/>
       </country>
       <country name="Panama">
           <rank>68</rank>
           <year>2011</year>
           <gdppc>13600</gdppc>
           <neighbor name="Costa Rica" direction="W"/>
           <neighbor name="Colombia" direction="E"/>
       </country>
   </data>

Podemos importar estos datos leyendo desde un archivo:

   import xml.etree.ElementTree as ET
   tree = ET.parse('country_data.xml')
   root = tree.getroot()

O directamente desde una cadena de caracteres:

   root = ET.fromstring(country_data_as_string)

"fromstring()" analiza el XML de una cadena de caracteres directamente
en un "Element", que es el elemento raíz del árbol analizado. Otras
funciones de análisis pueden crear un "ElementTree". Compruebe la
documentación para estar seguro.

Como un "Element", "root" tiene una etiqueta y un diccionario de
atributos:

   >>> root.tag
   'data'
   >>> root.attrib
   {}

También tiene nodos hijos sobre los cuales podemos iterar:

   >>> for child in root:
   ...     print(child.tag, child.attrib)
   ...
   country {'name': 'Liechtenstein'}
   country {'name': 'Singapore'}
   country {'name': 'Panama'}

Los hijos están anidados, y podemos acceder a nodos hijos específicos
por el índice:

   >>> root[0][1].text
   '2008'

Nota:

  No todos los elementos de la entrada XML acabarán siendo elementos
  del árbol analizado. Actualmente, este módulo omite cualquier
  comentario XML, instrucciones de procesamiento y declaraciones de
  tipo documento en la entrada. Sin embargo, los árboles construidos
  utilizando la API de este módulo, en lugar de analizar el texto XML,
  pueden contener comentarios e instrucciones de procesamiento, que se
  incluirán al generar la salida XML. Se puede acceder a una
  declaración de tipo documento pasando una instancia "TreeBuilder"
  personalizada al constructor "XMLParser".


API de consulta para un procesamiento no bloqueante
---------------------------------------------------

La mayoría de las funciones de análisis proporcionadas por este módulo
requieren que se lea todo el documento a la vez antes de retornar
cualquier resultado. Es posible utilizar un "XMLParser" y alimentar
los datos en él de forma incremental, pero se trata de una *push* API
que llama a métodos en un objetivo invocable, que es demasiado bajo
nivel e inconveniente para la mayoría de las necesidades. A veces, lo
que el usuario realmente quiere es ser capaz de analizar XML de forma
incremental, sin bloquear las operaciones, mientras disfruta de la
comodidad de los objetos "Element" totalmente construidos.

La herramienta más potente para hacer esto es "XMLPullParser". No
requiere una lectura de bloqueo para obtener los datos XML, y en su
lugar se alimenta de datos de forma incremental con llamadas a
"XMLPullParser.feed()". Para obtener los elementos XML analizados,
llama a "XMLPullParser.read_events()". He aquí un ejemplo:

   >>> parser = ET.XMLPullParser(['start', 'end'])
   >>> parser.feed('<mytag>sometext')
   >>> list(parser.read_events())
   [('start', <Element 'mytag' at 0x7fa66db2be58>)]
   >>> parser.feed(' more text</mytag>')
   >>> for event, elem in parser.read_events():
   ...     print(event)
   ...     print(elem.tag, 'text=', elem.text)
   ...
   end

El caso de uso obvio es el de las aplicaciones que operan de forma no
bloqueante, donde los datos XML se reciben de un socket o se leen de
forma incremental desde algún dispositivo de almacenamiento. En estos
casos, las lecturas bloqueantes son inaceptables.

Debido a su flexibilidad, "XMLPullParser" puede ser un inconveniente
para los casos de uso más simples. Si no te importa que tu aplicación
se bloquee en la lectura de datos XML pero te gustaría tener
capacidades de análisis incremental, echa un vistazo a "iterparse()".
Puede ser útil cuando estás leyendo un documento XML grande y no
quieres mantenerlo completamente en memoria.


Encontrando elementos interesantes
----------------------------------

"Element" tiene algunos métodos útiles que ayudan a iterar
recursivamente sobre todo el sub-árbol por debajo de él (sus hijos,
los hijos de sus hijos, y así sucesivamente). Por ejemplo,
"Element.iter()":

   >>> for neighbor in root.iter('neighbor'):
   ...     print(neighbor.attrib)
   ...
   {'name': 'Austria', 'direction': 'E'}
   {'name': 'Switzerland', 'direction': 'W'}
   {'name': 'Malaysia', 'direction': 'N'}
   {'name': 'Costa Rica', 'direction': 'W'}
   {'name': 'Colombia', 'direction': 'E'}

"Element.findall()" encuentra sólo los elementos con una etiqueta que
son hijos directos del elemento actual. "Element.find()" encuentra el
*primer* hijo con una etiqueta determinada, y "Element.text" accede al
contenido de texto del elemento. "Element.get()" accede a los
atributos del elemento:

   >>> for country in root.findall('country'):
   ...     rank = country.find('rank').text
   ...     name = country.get('name')
   ...     print(name, rank)
   ...
   Liechtenstein 1
   Singapore 4
   Panama 68

Es posible especificar de forma más sofisticada qué elementos buscar
utilizando XPath.


Modificando un archivo XML
--------------------------

"ElementTree" proporciona una forma sencilla de construir documentos
XML y escribirlos en archivos. El método "ElementTree.write()" sirve
para este propósito.

Una vez creado, un objeto "Element" puede ser manipulado cambiando
directamente sus campos (como "Element.text"), añadiendo y modificando
atributos (método "Element.set()"), así como añadiendo nuevos hijos
(por ejemplo con "Element.append()").

Digamos que queremos añadir uno al rango de cada país, y añadir un
atributo "updated" al elemento rango:

   >>> for rank in root.iter('rank'):
   ...     new_rank = int(rank.text) + 1
   ...     rank.text = str(new_rank)
   ...     rank.set('updated', 'yes')
   ...
   >>> tree.write('output.xml')

Nuestro XML tiene ahora este aspecto:

   <?xml version="1.0"?>
   <data>
       <country name="Liechtenstein">
           <rank updated="yes">2</rank>
           <year>2008</year>
           <gdppc>141100</gdppc>
           <neighbor name="Austria" direction="E"/>
           <neighbor name="Switzerland" direction="W"/>
       </country>
       <country name="Singapore">
           <rank updated="yes">5</rank>
           <year>2011</year>
           <gdppc>59900</gdppc>
           <neighbor name="Malaysia" direction="N"/>
       </country>
       <country name="Panama">
           <rank updated="yes">69</rank>
           <year>2011</year>
           <gdppc>13600</gdppc>
           <neighbor name="Costa Rica" direction="W"/>
           <neighbor name="Colombia" direction="E"/>
       </country>
   </data>

Podemos eliminar elementos utilizando "Element.remove()". Digamos que
queremos eliminar todos los países con un rango superior a 50:

   >>> for country in root.findall('country'):
   ...     # using root.findall() to avoid removal during traversal
   ...     rank = int(country.find('rank').text)
   ...     if rank > 50:
   ...         root.remove(country)
   ...
   >>> tree.write('output.xml')

Tenga en cuenta que la modificación concurrente mientras se itera
puede conducir a problemas, al igual que cuando se itera y modifica
listas o diccionarios de Python. Por lo tanto, el ejemplo recoge
primero todos los elementos coincidentes con "root.findall()", y sólo
entonces itera sobre la lista de coincidencias.

Nuestro XML tiene ahora este aspecto:

   <?xml version="1.0"?>
   <data>
       <country name="Liechtenstein">
           <rank updated="yes">2</rank>
           <year>2008</year>
           <gdppc>141100</gdppc>
           <neighbor name="Austria" direction="E"/>
           <neighbor name="Switzerland" direction="W"/>
       </country>
       <country name="Singapore">
           <rank updated="yes">5</rank>
           <year>2011</year>
           <gdppc>59900</gdppc>
           <neighbor name="Malaysia" direction="N"/>
       </country>
   </data>


Construyendo documentos XML
---------------------------

La función "SubElement()" también proporciona una forma cómoda de
crear nuevos sub-elementos para un elemento dado:

   >>> a = ET.Element('a')
   >>> b = ET.SubElement(a, 'b')
   >>> c = ET.SubElement(a, 'c')
   >>> d = ET.SubElement(c, 'd')
   >>> ET.dump(a)
   <a><b /><c><d /></c></a>


Procesando XML con espacio de nombres
-------------------------------------

Si la entrada XML tiene espacio de nombres, las etiquetas y los
atributos con prefijos de la forma "prefix:sometag" se expanden a
"{uri}sometag" donde el *prefix* se sustituye por el *URI* completo.
Además, si hay un espacio de nombre por defecto, ese URI completo se
antepone a todas las etiquetas sin prefijo.

A continuación se muestra un ejemplo de XML que incorpora dos espacios
de nombres, uno con el prefijo "fictional" y el otro que sirve como
espacio de nombres por defecto:

   <?xml version="1.0"?>
   <actors xmlns:fictional="http://characters.example.com"
           xmlns="http://people.example.com">
       <actor>
           <name>John Cleese</name>
           <fictional:character>Lancelot</fictional:character>
           <fictional:character>Archie Leach</fictional:character>
       </actor>
       <actor>
           <name>Eric Idle</name>
           <fictional:character>Sir Robin</fictional:character>
           <fictional:character>Gunther</fictional:character>
           <fictional:character>Commander Clement</fictional:character>
       </actor>
   </actors>

Una forma de buscar y explorar este ejemplo XML es añadir manualmente
el URI a cada etiqueta o atributo en el XPath de un "find()" o
"findall()":

   root = fromstring(xml_text)
   for actor in root.findall('{http://people.example.com}actor'):
       name = actor.find('{http://people.example.com}name')
       print(name.text)
       for char in actor.findall('{http://characters.example.com}character'):
           print(' |-->', char.text)

Una mejor manera de buscar en el ejemplo de XML con espacio para
nombres es crear un diccionario con sus propios prefijos y utilizarlos
en las funciones de búsqueda:

   ns = {'real_person': 'http://people.example.com',
         'role': 'http://characters.example.com'}

   for actor in root.findall('real_person:actor', ns):
       name = actor.find('real_person:name', ns)
       print(name.text)
       for char in actor.findall('role:character', ns):
           print(' |-->', char.text)

Estos dos enfoques dan como resultado:

   John Cleese
    |--> Lancelot
    |--> Archie Leach
   Eric Idle
    |--> Sir Robin
    |--> Gunther
    |--> Commander Clement


Soporte de XPath
================

Este módulo proporciona un soporte limitado para las expresiones XPath
para localizar elementos en un árbol. El objetivo es soportar un
pequeño subconjunto de la sintaxis abreviada; un motor XPath completo
está fuera del alcance del módulo.


Ejemplo
-------

A continuación se muestra un ejemplo que demuestra algunas de las
capacidades de XPath del módulo. Utilizaremos el documento XML
"countrydata" de la sección Parsing XML:

   import xml.etree.ElementTree as ET

   root = ET.fromstring(countrydata)

   # Top-level elements
   root.findall(".")

   # All 'neighbor' grand-children of 'country' children of the top-level
   # elements
   root.findall("./country/neighbor")

   # Nodes with name='Singapore' that have a 'year' child
   root.findall(".//year/..[@name='Singapore']")

   # 'year' nodes that are children of nodes with name='Singapore'
   root.findall(".//*[@name='Singapore']/year")

   # All 'neighbor' nodes that are the second child of their parent
   root.findall(".//neighbor[2]")

Para XML con espacios de nombre, use la notación calificada habitual
"{namespace}tag":

   # All dublin-core "title" tags in the document
   root.findall(".//{http://purl.org/dc/elements/1.1/}title")


Sintaxis XPath soportada
------------------------

+-------------------------+--------------------------------------------------------+
| Sintaxis                | Significado                                            |
|=========================|========================================================|
| "tag"                   | Selecciona todos los elementos hijos con la etiqueta   |
|                         | dada. Por ejemplo, "spam" selecciona todos los         |
|                         | elementos hijos llamados "spam", y "spam/egg"          |
|                         | selecciona todos los nietos llamados "egg" en todos    |
|                         | los hijos llamados "spam". "{namespace}*" selecciona   |
|                         | todas las etiquetas en el espacio de nombres dado,     |
|                         | "{*}spam" selecciona las etiquetas llamadas "spam" en  |
|                         | cualquier (o ningún) espacio de nombres, y "{}*" sólo  |
|                         | selecciona las etiquetas que no están en un espacio de |
|                         | nombres.  Distinto en la versión 3.8: Se ha añadido la |
|                         | posibilidad de utilizar comodines asterisco.           |
+-------------------------+--------------------------------------------------------+
| "*"                     | Selecciona todos los elementos hijos, incluidos los    |
|                         | comentarios y las instrucciones de procesamiento. Por  |
|                         | ejemplo, "*/egg" selecciona todos los hijos llamados   |
|                         | "egg".                                                 |
+-------------------------+--------------------------------------------------------+
| "."                     | Selecciona el nodo actual. Esto es útil sobre todo al  |
|                         | principio de la ruta, para indicar que es una ruta     |
|                         | relativa.                                              |
+-------------------------+--------------------------------------------------------+
| "//"                    | Selecciona todos los sub-elementos, en todos los       |
|                         | niveles por debajo del elemento actual. Por ejemplo,   |
|                         | ".//egg" selecciona todos los elementos "egg" en todo  |
|                         | el árbol.                                              |
+-------------------------+--------------------------------------------------------+
| ".."                    | Selecciona el elemento padre. Retorna "None" si la     |
|                         | ruta intenta llegar a los ancestros del elemento       |
|                         | inicial (el elemento "find" fue invocado).             |
+-------------------------+--------------------------------------------------------+
| "[@attrib]"             | Selecciona todos los elementos que tengan el atributo  |
|                         | dado.                                                  |
+-------------------------+--------------------------------------------------------+
| "[@attrib='value']"     | Selecciona todos los elementos para los que el         |
|                         | atributo dado tiene el valor dado. El valor no puede   |
|                         | contener comillas.                                     |
+-------------------------+--------------------------------------------------------+
| "[tag]"                 | Selecciona todos los elementos que tienen un hijo      |
|                         | llamado "tag". Sólo se admiten los hijos inmediatos.   |
+-------------------------+--------------------------------------------------------+
| "[.='text']"            | Selecciona todos los elementos cuyo contenido de texto |
|                         | completo, incluyendo los descendientes, es igual al    |
|                         | "texto" dado.  Nuevo en la versión 3.7.                |
+-------------------------+--------------------------------------------------------+
| "[tag='text']"          | Selecciona todos los elementos que tienen un hijo      |
|                         | llamado "tag" cuyo contenido de texto completo,        |
|                         | incluyendo los descendientes, es igual al "text" dado. |
+-------------------------+--------------------------------------------------------+
| "[position]"            | Selecciona todos los elementos que se encuentran en la |
|                         | posición dada. La posición puede ser un número entero  |
|                         | (1 es la primera posición), la expresión "last()"      |
|                         | (para la última posición), o una posición relativa a   |
|                         | la última posición (por ejemplo, "last()-1").          |
+-------------------------+--------------------------------------------------------+

Los predicados (expresiones entre corchetes) deben ir precedidos de un
nombre de etiqueta, un asterisco u otro predicado. Los predicados
"position" deben ir precedidos de un nombre de etiqueta.


Referencia
==========


Funciones
---------

xml.etree.ElementTree.canonicalize(xml_data=None, *, out=None, from_file=None, **options)

   Función de transformación C14N 2.0.

   La canonización es una forma de normalizar la salida de XML de
   manera que permita comparaciones byte a byte y firmas digitales.
   Reduce la libertad que tienen los serializadores XML y en su lugar
   genera una representación XML más restringida. Las principales
   restricciones se refieren a la colocación de las declaraciones de
   espacio de nombres, el orden de los atributos y los espacios en
   blanco ignorables.

   Esta función toma una cadena de datos XML (*xml_data*) o una ruta
   de archivo o un objeto tipo archivo (*from_file*) como entrada, la
   convierte a la forma canónica y la escribe utilizando el objeto
   archivo (o tipo archivo) *out*, si se proporciona, o la devuelve
   como una cadena de texto si no. El archivo de salida recibe texto,
   no bytes. Por tanto, debe abrirse en modo texto con codificación
   "utf-8".

   Usos típicos:

      xml_data = "<root>...</root>"
      print(canonicalize(xml_data))

      with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file:
          canonicalize(xml_data, out=out_file)

      with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file:
          canonicalize(from_file="inputfile.xml", out=out_file)

   Las opciones de configuración *options* son las siguientes:

   * *with_comments*: configurar a "True" para incluir los comentarios
     (por defecto: "False")

   * *strip_text*: configurar a "True" para eliminar los espacios en
     blanco antes y después del contenido del texto
        (por defecto: "False")

   * *rewrite_prefixes*: configurar a "True" para sustituir los
     prefijos de espacios de nombres por "n{number}"
        (por defecto: "False")

   * *qname_aware_tags*: un conjunto de nombres de etiquetas
     conscientes de qname en el que los prefijos
        deben ser reemplazados en el contenido del texto (por defecto:
        vacío)

   * *qname_aware_attrs*: un conjunto de nombres de atributos
     conscientes de qname en el que los prefijos
        deben ser reemplazados en el contenido del texto (por defecto:
        vacío)

   * *exclude_attrs*: un conjunto de nombres de atributos que no deben
     serializarse

   * *exclude_tags*: un conjunto de nombres de etiquetas que no deben
     serializarse

   En la lista de opciones anterior, "un conjunto" se refiere a
   cualquier colección o iterable de cadenas, no se espera ningún
   orden.

   Nuevo en la versión 3.8.

xml.etree.ElementTree.Comment(text=None)

   Fábrica de elementos de comentario. Esta función de fábrica crea un
   elemento especial que será serializado como un comentario XML por
   el serializador estándar. La cadena de comentario puede ser una
   cadena de bytes o una cadena Unicode. *text* es una cadena que
   contiene la cadena de comentario. Devuelve una instancia de
   elemento que representa un comentario.

   Tenga en cuenta que "XMLParser" omite los comentarios en la entrada
   en lugar de crear objetos de comentario para ellos. Un
   "ElementTree" sólo contendrá nodos de comentario si se han
   insertado en el árbol utilizando uno de los métodos "Element".

xml.etree.ElementTree.dump(elem)

   Escribe un árbol de elementos o una estructura de elementos en
   sys.stdout. Esta función debe utilizarse únicamente para debugging.

   El formato de salida exacto depende de la implementación. En esta
   versión, se escribe como un archivo XML ordinario.

   *elem* es un árbol de elementos o un elemento individual.

   Distinto en la versión 3.8: La función "dump()" ahora preserva el
   orden de atributos especificado por el usuario.

xml.etree.ElementTree.fromstring(text, parser=None)

   Analiza una sección XML a partir de una constante de cadena. Igual
   que "XML()". *text* es una cadena que contiene datos XML. *parser*
   es una instancia de parser opcional. Si no se da, se utiliza el
   analizador estándar "XMLParser". Devuelve una instancia de
   "Element".

xml.etree.ElementTree.fromstringlist(sequence, parser=None)

   Analiza un documento XML a partir de una secuencia de fragmentos de
   cadena de caracteres. *sequence* es una lista u otra secuencia que
   contiene fragmentos de datos XML. *parser* es una instancia de
   parser opcional. Si no se da, se utiliza el analizador estándar
   "XMLParser". Retorna una instancia de "Element".

   Nuevo en la versión 3.2.

xml.etree.ElementTree.indent(tree, space="  ", level=0)

   Añade espacios en blanco al subárbol para indentar el árbol
   visualmente. Esto puede utilizarse para generar una salida XML con
   una impresión bonita. *tree* puede ser un Element o ElementTree.
   *space* es la cadena de espacio en blanco que se insertará para
   cada nivel de indentación, dos caracteres de espacio por defecto.
   Para indentar subárboles parciales dentro de un árbol ya indentado,
   pase el nivel de indentación inicial como *level*.

   Nuevo en la versión 3.9.

xml.etree.ElementTree.iselement(element)

   Comprueba si un objeto parece ser un objeto elemento válido.
   *element* es una instancia de elemento. Retorna "True" si se trata
   de un objeto elemento.

xml.etree.ElementTree.iterparse(source, events=None, parser=None)

   Analiza una sección XML en un árbol de elementos de forma
   incremental, e informa al usuario de lo que ocurre. *source* es un
   nombre de archivo o un *file object* que contiene datos XML.
   *events* es una secuencia de eventos para informar. Los eventos
   soportados son las cadenas ""start"", ""end"", ""comment"", ""pi"",
   ""start-ns"" y ""end-ns"" (los eventos "ns" se utilizan para
   obtener información detallada del espacio de nombres). Si se omite
   *events*, sólo se informará de los eventos ""end"". *parser* es una
   instancia opcional de parser. Si no se da, se utiliza el analizador
   estándar de "XMLParser". *parser* debe ser una subclase de
   "XMLParser" y sólo puede utilizar el "TreeBuilder" por defecto como
   objetivo. Devuelve un *iterator* que proporciona pares "(event,
   elem)".

   Tenga en cuenta que mientras "iterparse()" construye el árbol de
   forma incremental, emite lecturas de bloqueo en la *source* (o en
   el fichero que nombra). Por lo tanto, no es adecuado para
   aplicaciones en las que no se pueden realizar lecturas de bloqueo.
   Para un análisis completamente no bloqueante, véase
   "XMLPullParser".

   Nota:

     "iterparse()" sólo garantiza que ha visto el carácter ">" de una
     etiqueta de inicio cuando emite un evento "start", por lo que los
     atributos están definidos, pero el contenido de los atributos
     text y tail está indefinido en ese momento. Lo mismo ocurre con
     los hijos del elemento; pueden estar presentes o no.Si necesita
     un elemento totalmente poblado, busque los eventos "end" en su
     lugar.

   Obsoleto desde la versión 3.4: El argumento *parser*.

   Distinto en la versión 3.8: Los eventos "comment" y "pi" han sido
   añadidos.

xml.etree.ElementTree.parse(source, parser=None)

   Analiza una sección XML en un árbol de elementos. *source* es un
   nombre de archivo o un objeto de archivo que contiene datos XML.
   *parser* es una instancia de parser opcional. Si no se da, se
   utiliza el analizador estándar "XMLParser". Devuelve una instancia
   de "ElementTree".

xml.etree.ElementTree.ProcessingInstruction(target, text=None)

   Fábrica de elementos PI. Esta función de fábrica crea un elemento
   especial que será serializado como una instrucción de procesamiento
   XML. *target* es una cadena que contiene el objetivo de PI. *text*
   es una cadena que contiene el contenido de PI, si se da. Devuelve
   una instancia de elemento, representando una instrucción de
   procesamiento.

   Tenga en cuenta que "XMLParser" omite las instrucciones de
   procesamiento en la entrada en lugar de crear objetos de comentario
   para ellas. Un "ElementTree" sólo contendrá nodos de instrucciones
   de procesamiento si se han insertado en el árbol utilizando uno de
   los métodos "Element".

xml.etree.ElementTree.register_namespace(prefix, uri)

   Registra un prefijo de espacio de nombres. El registro es global, y
   cualquier asignación existente para el prefijo dado o el URI del
   espacio de nombres será eliminado. *prefix* es un prefijo de
   espacio de nombres. *uri* es una uri del espacio de nombres. Las
   etiquetas y los atributos de este espacio de nombres se
   serializarán con el prefijo dado, si es posible.

   Nuevo en la versión 3.2.

xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)

   Fábrica de sub-elementos. Esta función crea una instancia de
   elemento y la añade a un elemento existente.

   El nombre del elemento, los nombres de los atributos y los valores
   de los atributos pueden ser cadenas de bytes o cadenas de
   caracteres Unicode. *parent* es el elemento padre. *tag* es el
   nombre del sub-elemento. *attrib* es un diccionario opcional que
   contiene los atributos del elemento. *extra* contiene atributos
   adicionales, dados como argumentos de palabras clave. Devuelve una
   instancia de elemento.

xml.etree.ElementTree.tostring(element, encoding="us-ascii", method="xml", *, xml_declaration=None, default_namespace=None, short_empty_elements=True)

   Genera una representación de cadena de caracteres de un elemento
   XML, incluyendo todos los sub-elementos. *element* es una instancia
   de "Element". *encoding* [1] es la codificación de salida (por
   defecto es US-ASCII). Utilice "encoding="unicode"" para generar una
   cadena de caracteres Unicode (de lo contrario, se genera una cadena
   de bytes). *method* es ""xml"", ""html"" o ""text"" (por defecto es
   ""xml""). *xml_declaration*, *default_namespace* y
   *short_empty_elements* tienen el mismo significado que en
   "ElementTree.write()". Devuelve una cadena (opcionalmente)
   codificada que contiene los datos XML.

   Nuevo en la versión 3.4: El parámetro *short_empty_elements*.

   Nuevo en la versión 3.8: Los parámetros *xml_declaration* y
   *default_namespace*.

   Distinto en la versión 3.8: La función "tostring()" ahora preserva
   el orden de atributos especificado por el usuario.

xml.etree.ElementTree.tostringlist(element, encoding="us-ascii", method="xml", *, xml_declaration=None, default_namespace=None, short_empty_elements=True)

   Genera una representación de cadena de caracteres de un elemento
   XML, incluyendo todos los sub-elementos. *element* es una instancia
   de "Element". *encoding* [1] es la codificación de salida (por
   defecto es US-ASCII). Utilice "encoding="unicode"" para generar una
   cadena de caracteres Unicode (de lo contrario, se genera una cadena
   de bytes). *method* es ""xml"", ""html"" o ""text"" (por defecto es
   ""xml""). *xml_declaration*, *default_namespace* y
   *short_empty_elements* tienen el mismo significado que en
   "ElementTree.write()". Devuelve una lista de cadenas
   (opcionalmente) codificadas que contienen los datos XML. No
   garantiza ninguna secuencia específica, excepto que
   "b"".join(tostringlist(element)) == tostring(element)".

   Nuevo en la versión 3.2.

   Nuevo en la versión 3.4: El parámetro *short_empty_elements*.

   Nuevo en la versión 3.8: Los parámetros *xml_declaration* y
   *default_namespace*.

   Distinto en la versión 3.8: La función "tostringlist()" ahora
   preserva el orden de atributos especificado por el usuario.

xml.etree.ElementTree.XML(text, parser=None)

   Analiza una sección XML a partir de una constante de cadena de
   caracteres. Esta función puede utilizarse para incrustar "literales
   XML" en el código de Python. *text* es una cadena de caracteres que
   contiene datos XML. *parser* es una instancia de parser opcional.
   Si no se da, se utiliza el analizador estándar "XMLParser".
   Devuelve una instancia de "Element".

xml.etree.ElementTree.XMLID(text, parser=None)

   Analiza una sección XML a partir de una constante de cadena de
   caracteres, y también devuelve un diccionario que mapea los id:s de
   elementos a elementos. *text* es una cadena de caracteres que
   contiene datos XML. *parser* es una instancia de parser opcional.
   Si no se da, se utiliza el analizador estándar de "XMLParser".
   Devuelve una tupla que contiene una instancia de "Element" y un
   diccionario.


Soporte de XInclude
===================

Este módulo proporciona un soporte limitado para las directivas
XInclude, a través del módulo de ayuda "xml.etree.ElementInclude".
Este módulo puede utilizarse para insertar subárboles y cadenas de
texto en árboles de elementos, basándose en la información del árbol.


Ejemplo
-------

Aquí hay un ejemplo que demuestra el uso del módulo XInclude. Para
incluir un documento XML en el documento actual, utilice el elemento
"{http://www.w3.org/2001/XInclude}include" y establezca el atributo
**parse** como ""xml"", y utilice el atributo **href** para
especificar el documento a incluir.

   <?xml version="1.0"?>
   <document xmlns:xi="http://www.w3.org/2001/XInclude">
     <xi:include href="source.xml" parse="xml" />
   </document>

Por defecto, el atributo **href** se trata como un nombre de archivo.
Puede utilizar cargadores personalizados para anular este
comportamiento. También tenga en cuenta que el ayudante estándar no
soporta la sintaxis XPointer.

Para procesar este archivo, cárguelo como de costumbre y pase el
elemento raíz al módulo "xml.etree.ElementTree":

   from xml.etree import ElementTree, ElementInclude

   tree = ElementTree.parse("document.xml")
   root = tree.getroot()

   ElementInclude.include(root)

El módulo ElementInclude sustituye el elemento
"{http://www.w3.org/2001/XInclude}include" por el elemento raíz del
documento **source.xml**. El resultado podría ser algo así:

   <document xmlns:xi="http://www.w3.org/2001/XInclude">
     <para>This is a paragraph.</para>
   </document>

Si se omite el atributo **parse**, el valor por defecto es "xml". El
atributo href es obligatorio.

Para incluir un documento de texto, utilice el elemento
"{http://www.w3.org/2001/XInclude}include" y establezca el atributo
**parse** como "text":

   <?xml version="1.0"?>
   <document xmlns:xi="http://www.w3.org/2001/XInclude">
     Copyright (c) <xi:include href="year.txt" parse="text" />.
   </document>

El resultado podría ser algo así:

   <document xmlns:xi="http://www.w3.org/2001/XInclude">
     Copyright (c) 2003.
   </document>


Referencia
==========


Funciones
---------

xml.etree.ElementInclude.default_loader(href, parse, encoding=None)

   Cargador por defecto. Este cargador por defecto lee un recurso
   incluido del disco. *href* es una URL. *parse* es para el modo de
   análisis "xml" o "text". *encoding* es una codificación de texto
   opcional. Si no se da, la codificación es "utf-8". Retorna el
   recurso expandido. Si el modo de análisis es ""xml"", es una
   instancia de ElementTree. Si el modo de análisis es "text", se
   trata de una cadena Unicode. Si el cargador falla, puede retornar
   None o lanzar una excepción.

xml.etree.ElementInclude.include(elem, loader=None, base_url=None, max_depth=6)

   Esta función expande las directivas XInclude. *elem* es el elemento
   raíz. *loader* es un cargador de recursos opcional. Si se omite, se
   utiliza por defecto "default_loader()". Si se da, debe ser un
   callable que implemente la misma interfaz que "default_loader()".
   *base_url* es la URL base del archivo original, para resolver las
   referencias relativas al archivo de inclusión. *max_depth* es el
   número máximo de inclusiones recursivas. Limitado para reducir el
   riesgo de explosión de contenido malicioso. Pase un valor negativo
   para desactivar la limitación.

   Retorna el recurso expandido. Si el modo de análisis es ""xml"", se
   trata de una instancia de ElementTree. Si el modo de análisis es
   "text", se trata de una cadena Unicode. Si el cargador falla, puede
   retornar None o lanzar una excepción.

   Nuevo en la versión 3.9: Los parámetros *base_url* y *max_depth*.


Objetos Element
---------------

class xml.etree.ElementTree.Element(tag, attrib={}, **extra)

   Clase Element. Esta clase define la interfaz Element, y provee una
   implementación de referencia de esta interfaz.

   El nombre del elemento, los nombres de los atributos y los valores
   de los atributos pueden ser cadenas de bytes o cadenas Unicode.
   *tag* es el nombre del elemento. *attrib* es un diccionario
   opcional que contiene los atributos del elemento. *extra* contiene
   atributos adicionales, dados como argumentos de palabras clave.

   tag

      Una cadena de caracteres que identifica qué tipo de datos
      representa este elemento (el tipo de elemento, en otras
      palabras).

   text
   tail

      Estos atributos pueden utilizarse para contener datos
      adicionales asociados al elemento. Sus valores suelen ser
      cadenas, pero pueden ser cualquier objeto específico de la
      aplicación. Si el elemento se crea a partir de un archivo XML,
      el atributo *text* contiene el texto entre la etiqueta inicial
      del elemento y su primera etiqueta hija o final, o "None", y el
      atributo *tail* contiene el texto entre la etiqueta final del
      elemento y la siguiente etiqueta, o "None". Para los datos XML

         <a><b>1<c>2<d/>3</c></b>4</a>

      el elemento *a* tiene "None" para los atributos *text* y *tail*,
      el elemento *b* tiene *text* ""1"" y *tail* ""4"", el elemento
      *c* tiene *text* ""2"" y *tail* "None", y el elemento *d* tiene
      *text* "None" y *tail* ""3"".

      Para recoger el texto interior de un elemento, véase
      "itertext()", por ejemplo """.join(element.itertext())".

      Las aplicaciones pueden almacenar objetos arbitrarios en estos
      atributos.

   attrib

      Un diccionario que contiene los atributos del elemento. Ten en
      cuenta que aunque el valor *attrib* es siempre un diccionario
      mutable real de Python, una implementación de ElementTree puede
      elegir utilizar otra representación interna, y crear el
      diccionario sólo si alguien lo pide. Para aprovechar este tipo
      de implementaciones, utiliza los métodos de diccionario que
      aparecen a continuación siempre que sea posible.

   Los siguientes métodos tipo diccionario funcionan con los atributos
   de los elementos.

   clear()

      Restablece un elemento.  Esta función elimina todos los sub-
      elementos, borra todos los atributos y establece los atributos
      de texto y cola como "None".

   get(key, default=None)

      Obtiene el atributo del elemento llamado *key*.

      Retorna el valor del atributo, o *default* si el atributo no fue
      encontrado.

   items()

      Retorna los atributos del elemento como una secuencia de pares
      (nombre, valor). Los atributos se retornan en un orden
      arbitrario.

   keys()

      Retorna los nombres de los atributos de los elementos como una
      lista. Los nombres se retornan en un orden arbitrario.

   set(key, value)

      Establecer el atributo *key* en el elemento a *value*.

   Los siguientes métodos actúan sobre los hijos del elemento (sub-
   elementos).

   append(subelement)

      Añade el elemento *subelement* al final de la lista interna de
      sub-elementos de este elemento. Lanza "TypeError" si
      *subelement* no es un "Element".

   extend(subelements)

      Añade *subelements* de un objeto de secuencia con cero o más
      elementos. Lanza "TypeError" si un sub-elemento no es un
      "Element".

      Nuevo en la versión 3.2.

   find(match, namespaces=None)

      Encuentra el primer sub-elemento que coincide con *match*.
      *match* puede ser un nombre de etiqueta o un path. Retorna una
      instancia de elemento o "None". *namespaces* es un mapeo
      opcional del prefijo del espacio de nombres al nombre completo.
      Pasa "''" como prefijo para mover todos los nombres de etiquetas
      sin prefijo en la expresión al espacio de nombres dado.

   findall(match, namespaces=None)

      Encuentra todos los sub-elementos coincidentes, por nombre de
      etiqueta o path. Retorna una lista que contiene todos los
      elementos coincidentes en el orden del documento. *namespaces*
      es un mapeo opcional del prefijo del espacio de nombres al
      nombre completo. Pasa "''" como prefijo para mover todos los
      nombres de etiquetas sin prefijo en la expresión al espacio de
      nombres dado.

   findtext(match, default=None, namespaces=None)

      Busca el texto del primer sub-elemento que coincida con *match*.
      *match* puede ser un nombre de etiqueta o un path. Retorna el
      contenido del texto del primer elemento que coincida, o
      *default* si no se encuentra ningún elemento. Tenga en cuenta
      que si el elemento coincidente no tiene contenido de texto se
      devuelve una cadena vacía. *namespaces* es un mapeo opcional del
      prefijo del espacio de nombres al nombre completo. Pasa "''"
      como prefijo para mover todos los nombres de etiquetas sin
      prefijo en la expresión al espacio de nombres dado.

   insert(index, subelement)

      Inserta *subelement* en la posición dada en este elemento. Lanza
      "TypeError" si *subelement* no es un "Element".

   iter(tag=None)

      Crea un árbol *iterator* con el elemento actual como raíz. El
      iterador itera sobre este elemento y todos los elementos por
      debajo de él, en el orden del documento (profundidad primero).
      Si *tag* no es "None" o "'*'", sólo los elementos cuya etiqueta
      es igual a *tag* son retornados por el iterador. Si la
      estructura del árbol se modifica durante la iteración, el
      resultado es indefinido.

      Nuevo en la versión 3.2.

   iterfind(match, namespaces=None)

      Encuentra todos los subelementos que coinciden, por nombre de
      etiqueta o ruta. Retorna un iterable con todos los elementos
      coincidentes en el orden del documento. *namespaces* es un mapeo
      opcional del prefijo del espacio de nombres al nombre completo.

      Nuevo en la versión 3.2.

   itertext()

      Crea un iterador de texto. El iterador hace un bucle sobre este
      elemento y todos los subelementos, en el orden del documento, y
      retorna todo el texto interior.

      Nuevo en la versión 3.2.

   makeelement(tag, attrib)

      Crea un nuevo objeto elemento del mismo tipo que este elemento.
      No llame a este método, utilice la función de fábrica
      "SubElement()" en su lugar.

   remove(subelement)

      Elimina el *subelement* del elemento. A diferencia de los
      métodos find*, este método compara los elementos basándose en la
      identidad de la instancia, no en el valor de la etiqueta o el
      contenido.

   Los objetos "Element" también soportan los siguientes métodos de
   tipo secuencia para trabajar con subelementos: "__delitem__()",
   "__getitem__()", "__setitem__()", "__len__()".

   Precaución: Los elementos que no tengan subelementos serán
   evaluados como "False". Este comportamiento cambiará en futuras
   versiones. Utilizar en su lugar el test específico "len(elem)" o
   "elem is None".

      element = root.find('foo')

      if not element:  # careful!
          print("element not found, or element has no subelements")

      if element is None:
          print("element not found")

   Antes de Python 3.8, el orden de serialización de los atributos XML
   de los elementos se hacía predecible artificialmente ordenando los
   atributos por su nombre. Basado en el ordenamiento -ahora
   garantizado- de los diccionarios, este reordenamiento arbitrario
   fue eliminado en Python 3.8 para preservar el orden en que los
   atributos fueron originalmente analizados o creados por el código
   del usuario.

   En general, el código del usuario debería intentar no depender de
   un orden específico de los atributos, dado que el XML Information
   Set excluye explícitamente el orden de los atributos para
   transmitir información. El código debe estar preparado para hacer
   frente a cualquier orden en la entrada. En los casos en los que se
   requiere una salida XML determinista, por ejemplo, para la firma
   criptográfica o los conjuntos de datos de prueba, la serialización
   canónica está disponible con la función "canonicalize()".

   En los casos en los que la salida canónica no es aplicable, pero un
   orden de atributos específico sigue siendo deseable en la salida,
   el código debe tratar de crear los atributos directamente en el
   orden deseado, para evitar desajustes perceptivos para los lectores
   del código. En los casos en que esto es difícil de lograr, una
   receta como la siguiente se puede aplicar antes de la serialización
   para hacer cumplir un orden independientemente de la creación de
   elementos:

      def reorder_attributes(root):
          for el in root.iter():
              attrib = el.attrib
              if len(attrib) > 1:
                  # adjust attribute order, e.g. by sorting
                  attribs = sorted(attrib.items())
                  attrib.clear()
                  attrib.update(attribs)


Objetos ElementTree
-------------------

class xml.etree.ElementTree.ElementTree(element=None, file=None)

   Clase envoltorio de un ElementTree. Esta clase representa una
   jerarquía de elementos completa, y añade algún soporte extra para
   la serialización hacia y desde XML estándar.

   *element* es el elemento raíz. El árbol se inicializa con el
   contenido del *file* XML si se da.

   _setroot(element)

      Reemplaza el elemento raíz de este árbol. Esto descarta el
      contenido actual del árbol, y lo reemplaza con el elemento dado.
      Utilícelo con cuidado. *element* es una instancia de elemento.

   find(match, namespaces=None)

      Igual que "Element.find()", empezando por la raíz del árbol.

   findall(match, namespaces=None)

      Igual que "Element.findall()", empezando por la raíz del árbol.

   findtext(match, default=None, namespaces=None)

      Igual que "Element.findtext()", empezando por la raíz del árbol.

   getroot()

      Retorna el elemento raíz de este árbol.

   iter(tag=None)

      Crea y retorna un iterador de árbol para el elemento raíz. El
      iterador recorre todos los elementos de este árbol, en orden de
      sección. *tag* es la etiqueta a buscar (por defecto devuelve
      todos los elementos).

   iterfind(match, namespaces=None)

      Igual que "Element.iterfind()", empezando por la raíz del árbol.

      Nuevo en la versión 3.2.

   parse(source, parser=None)

      Carga una sección XML externa en este árbol de elementos.
      *source* es un nombre de archivo o un *file object*. *parser* es
      una instancia opcional del analizador. Si no se da, se utiliza
      el analizador estándar "XMLParser". Retorna el elemento raíz de
      la sección.

   write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml", *, short_empty_elements=True)

      Escribe el árbol de elementos en un archivo, como XML. *file* es
      un nombre de archivo, o un *file object* abierto para escritura.
      *encoding* [1] es la codificación de salida (por defecto es US-
      ASCII). *xml_declaration* controla si se debe añadir una
      declaración XML al archivo. Utilice "False" para nunca, "True"
      para siempre, "None" para sólo si no es US-ASCII o UTF-8 o
      Unicode (por defecto es "None"). *default_namespace* establece
      el espacio de nombres XML por defecto (para "xmlns"). *method*
      es ""xml"", ""html"" o ""text"" (por defecto es ""xml""). El
      parámetro *short_empty_elements* controla el formato de los
      elementos sin contenido. Si es "True" (por defecto), se emiten
      como una sola etiqueta autocerrada, de lo contrario se emiten
      como un par de etiquetas de inicio/fin.

      La salida es una cadena de caracteres ("str") o binaria
      ("bytes"). Esto es controlado por el argumento *encoding*. Si
      *encoding* es "unicode", la salida es una cadena de caracteres;
      en caso contrario, es binaria. Tenga en cuenta que esto puede
      entrar en conflicto con el tipo de *file* si es un *file object*
      abierto; asegúrese de no intentar escribir una cadena en un
      flujo binario y viceversa.

      Nuevo en la versión 3.4: El parámetro *short_empty_elements*.

      Distinto en la versión 3.8: El método "write()" ahora conserva
      el orden de los atributos especificado por el usuario.

Este es el archivo XML que será manipulado:

   <html>
       <head>
           <title>Example page</title>
       </head>
       <body>
           <p>Moved to <a href="http://example.org/">example.org</a>
           or <a href="http://example.com/">example.com</a>.</p>
       </body>
   </html>

Ejemplo de cambio del atributo "target" de cada enlace en el primer
párrafo:

   >>> from xml.etree.ElementTree import ElementTree
   >>> tree = ElementTree()
   >>> tree.parse("index.xhtml")
   <Element 'html' at 0xb77e6fac>
   >>> p = tree.find("body/p")     # Finds first occurrence of tag p in body
   >>> p
   <Element 'p' at 0xb77ec26c>
   >>> links = list(p.iter("a"))   # Returns list of all links
   >>> links
   [<Element 'a' at 0xb77ec2ac>, <Element 'a' at 0xb77ec1cc>]
   >>> for i in links:             # Iterates through all found links
   ...     i.attrib["target"] = "blank"
   >>> tree.write("output.xhtml")


Objetos QName
-------------

class xml.etree.ElementTree.QName(text_or_uri, tag=None)

   QName wrapper. Se puede utilizar para envolver un valor de atributo
   QName, con el fin de obtener un manejo adecuado del espacio de
   nombres en la salida. *text_or_uri* es una cadena de caracteres que
   contiene el valor QName, en la forma {uri}local, o, si se da el
   argumento tag, la parte URI de un QName. Si se da *tag*, el primer
   argumento se interpreta como un URI, y este argumento se interpreta
   como un nombre local. Las instancias de "QName" son opacas.


Objetos TreeBuilder
-------------------

class xml.etree.ElementTree.TreeBuilder(element_factory=None, *, comment_factory=None, pi_factory=None, insert_comments=False, insert_pis=False)

   Constructor genérico de estructuras de elementos. Este constructor
   convierte una secuencia de llamadas a los métodos start, data, end,
   comment y pi en una estructura de elementos bien formada. Puedes
   utilizar esta clase para construir una estructura de elementos
   utilizando un analizador XML personalizado, o un analizador para
   algún otro formato similar a XML.

   *element_factory*, cuando se da, debe ser un callable que acepta
   dos argumentos posicionales: una etiqueta y un diccionario de
   atributos. Se espera que retorne una nueva instancia de elemento.

   Las funciones *comment_factory* y *pi_factory*, cuando se dan,
   deben comportarse como las funciones "Comment()" y
   "ProcessingInstruction()" para crear comentarios e instrucciones de
   procesamiento. Si no se dan, se utilizarán las fábricas por
   defecto. Cuando *insert_comments* y/o *insert_pis* es verdadero,
   los comentarios/pis se insertarán en el árbol si aparecen dentro
   del elemento raíz (pero no fuera de él).

   close()

      Vacía los buffers del constructor y retorna el elemento del
      documento de nivel superior. Retorna una instancia de "Element".

   data(data)

      Añade texto al elemento actual. *data* es una cadena. Debe ser
      una cadena de bytes o una cadena Unicode.

   end(tag)

      Cierra el elemento actual. *tag* es el nombre del elemento.
      Retorna el elemento cerrado.

   start(tag, attrs)

      Abre un nuevo elemento. *tag* es el nombre del elemento. *attrs*
      es un diccionario que contiene los atributos del elemento.
      Retorna el elemento abierto.

   comment(text)

      Crea un comentario con el *texto* dado. Si "insert_comments" es
      verdadero, esto también lo añadirá al árbol.

      Nuevo en la versión 3.8.

   pi(target, text)

      Crea un comentario con el nombre *target* y el *texto* dados. Si
      "insert_pis" es verdadero, esto también lo añadirá al árbol.

      Nuevo en la versión 3.8.

   Además, un objeto "TreeBuilder" personalizado puede proporcionar
   los siguientes métodos:

   doctype(name, pubid, system)

      Maneja una declaración de doctype. *name* es el nombre del
      doctype. *pubid* es el identificador público. *system* es el
      identificador del sistema. Este método no existe en la clase por
      defecto "TreeBuilder".

      Nuevo en la versión 3.2.

   start_ns(prefix, uri)

      Se llama cada vez que el analizador encuentra una nueva
      declaración de espacio de nombres, antes de la llamada de
      retorno "start()" para el elemento de apertura que lo define.
      *prefix* es "''" para el espacio de nombres por defecto y el
      nombre del prefijo del espacio de nombres declarado en caso
      contrario. *uri* es el URI del espacio de nombres.

      Nuevo en la versión 3.8.

   end_ns(prefix)

      Se llama después de la llamada de retorno "end()" de un elemento
      que declaró un mapeo de prefijo de espacio de nombres, con el
      nombre del *prefijo* que salió del ámbito.

      Nuevo en la versión 3.8.

class xml.etree.ElementTree.C14NWriterTarget(write, *, with_comments=False, strip_text=False, rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None, exclude_attrs=None, exclude_tags=None)

   Un escritor C14N 2.0. Los argumentos son los mismos que para la
   función "canonicalize()". Esta clase no construye un árbol, sino
   que traduce los eventos de devolución de llamada directamente a una
   forma serializada utilizando la función *write*.

   Nuevo en la versión 3.8.


Objetos XMLParser
-----------------

class xml.etree.ElementTree.XMLParser(*, target=None, encoding=None)

   Esta clase es el bloque de construcción de bajo nivel del módulo.
   Utiliza "xml.parsers.expat" para un análisis eficiente de XML
   basado en eventos. Puede ser alimentada con datos XML de forma
   incremental con el método "feed()", y los eventos de análisis se
   traducen en una API push - invocando callbacks en el objeto
   *target*. Si se omite *target*, se utiliza la clase estándar
   "TreeBuilder". Si se da *encoding* [1], el valor anula la
   codificación especificada en el archivo XML.

   Distinto en la versión 3.8: Los parámetros son ahora keyword-only.
   El argumento *html* ya no se admite.

   close()

      Finaliza la alimentación de datos al analizador. Retorna el
      resultado de llamar al método "close()" del *target* pasado
      durante la construcción; por defecto, es el elemento del
      documento de nivel superior.

   feed(data)

      Introduce los datos en el analizador sintáctico. *data* son
      datos codificados.

   "XMLParser.feed()" llama al método "start(tag, attrs_dict)" de
   *target* para cada etiqueta de apertura, a su método "end(tag)"
   para cada etiqueta de cierre, y los datos son procesados por el
   método "data(data)". Para más métodos de callback soportados, véase
   la clase "TreeBuilder". "XMLParser.close()" llama al método
   "close()" de *target*. "XMLParser" puede utilizarse no sólo para
   construir una estructura de árbol. Este es un ejemplo de contar la
   profundidad máxima de un archivo XML:

      >>> from xml.etree.ElementTree import XMLParser
      >>> class MaxDepth:                     # The target object of the parser
      ...     maxDepth = 0
      ...     depth = 0
      ...     def start(self, tag, attrib):   # Called for each opening tag.
      ...         self.depth += 1
      ...         if self.depth > self.maxDepth:
      ...             self.maxDepth = self.depth
      ...     def end(self, tag):             # Called for each closing tag.
      ...         self.depth -= 1
      ...     def data(self, data):
      ...         pass            # We do not need to do anything with data.
      ...     def close(self):    # Called when all data has been parsed.
      ...         return self.maxDepth
      ...
      >>> target = MaxDepth()
      >>> parser = XMLParser(target=target)
      >>> exampleXml = """
      ... <a>
      ...   <b>
      ...   </b>
      ...   <b>
      ...     <c>
      ...       <d>
      ...       </d>
      ...     </c>
      ...   </b>
      ... </a>"""
      >>> parser.feed(exampleXml)
      >>> parser.close()
      4


Objetos XMLPullParser
---------------------

class xml.etree.ElementTree.XMLPullParser(events=None)

   Un analizador sintáctico pull adecuado para aplicaciones no
   bloqueantes. Su API de entrada es similar a la de "XMLParser", pero
   en lugar de enviar llamadas a un objetivo de devolución de llamada,
   "XMLPullParser" recoge una lista interna de eventos de análisis y
   permite al usuario leer de ella. *events* son una secuencia de
   eventos a reportar. Los eventos soportados son las cadenas
   ""start"", ""end"", ""comment"", ""pi"", ""start-ns"" y ""end-ns""
   (los eventos "ns" se utilizan para obtener información detallada
   del espacio de nombres). Si se omite *events*, sólo se informará de
   los eventos ""end"".

   feed(data)

      Introduce los datos de los bytes dados en el analizador.

   close()

      Señala al analizador que el flujo de datos ha terminado. A
      diferencia de "XMLParser.close()", este método siempre retorna
      "None". Cualquier evento que no haya sido recuperado cuando el
      analizador se cierra puede ser leído con "read_events()".

   read_events()

      Retorna un iterador sobre los eventos que se han encontrado en
      los datos alimentados al analizador. El iterador retorna pares
      "(event, elem)", donde *event* es una cadena de caracteres que
      representa el tipo de evento (por ejemplo, ""fin"") y *elem* es
      el objeto "Element" encontrado, u otro valor de contexto como el
      siguiente.

      * "start", "end": el Element actual.

      * "comment", "pi": el comentario / la instrucción de
        procesamiento actual

      * "start-ns": una tupla "(prefix, uri)" que nombra el mapeo del
        espacio de nombres declarado.

      * "end-ns": "None" (esto puede cambiar en una versión futura)

      Los eventos proporcionados en una llamada anterior a
      "read_events()" no serán retornados nuevamente. Los eventos se
      consumen de la cola interna sólo cuando se recuperan del
      iterador, por lo que múltiples lectores iterando en paralelo
      sobre iteradores obtenidos de "read_events()" tendrán resultados
      impredecibles.

   Nota:

     "XMLPullParser" sólo garantiza que ha visto el carácter ">" de
     una etiqueta de inicio cuando emite un evento "start", por lo que
     los atributos están definidos, pero el contenido de los atributos
     text y tail está indefinido en ese momento. Lo mismo ocurre con
     los hijos del elemento; pueden estar presentes o no.Si necesita
     un elemento totalmente poblado, busque los eventos "end" en su
     lugar.

   Nuevo en la versión 3.4.

   Distinto en la versión 3.8: Los eventos "comment" y "pi" han sido
   añadidos.


Excepciones
-----------

class xml.etree.ElementTree.ParseError

   Error de análisis de XML, lanzado por los distintos métodos de
   análisis de este módulo cuando el análisis falla. La representación
   en cadena de caracteres de una instancia de esta excepción
   contendrá un mensaje de error fácil de entender. Además, tendrá los
   siguientes atributos disponibles:

   code

      Un código de error numérico del analizador sintáctico expat.
      Consulte la documentación de "xml.parsers.expat" para ver la
      lista de códigos de error y sus significados.

   position

      Una tupla de números de *line*, *column*, que especifica dónde
      se produjo el error.

-[ Notas al pie de página ]-

[1] La cadena de caracteres de codificación incluida en la salida XML
    debe ajustarse a los estándares adecuados. Por ejemplo, "UTF-8" es
    válido, pero "UTF8" no lo es. Consulte https://www.w3.org/TR/2006
    /REC-xml11-20060816/#NT-EncodingDecl y
    https://www.iana.org/assignments/character-sets/character-
    sets.xhtml.
