Pregunta

He escrito una pequeña función, que utiliza elementtree y XPath para extraer el contenido de texto de ciertos elementos en un archivo XML:

#!/usr/bin/env python2.5

import doctest
from xml.etree import ElementTree
from StringIO import StringIO

def parse_xml_etree(sin, xpath):
  """
Takes as input a stream containing XML and an XPath expression.
Applies the XPath expression to the XML and returns a generator
yielding the text contents of each element returned.

>>> parse_xml_etree(
...   StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'),
...   '//elem1').next()
'one'
>>> parse_xml_etree(
...   StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'),
...   '//elem2').next()
'two'
>>> parse_xml_etree(
...   StringIO('<test><null>&#0;</null><elem3>three</elem3></test>'),
...   '//elem2').next()
'three'
"""

  tree = ElementTree.parse(sin)
  for element in tree.findall(xpath):
    yield element.text  

if __name__ == '__main__':
  doctest.testmod(verbose=True)

La tercera prueba falla con la siguiente excepción:

ExpatError: referencia a inválido número de caracteres: línea 1, columna 13

Es el XML ilegal entidad &#0;? Independientemente de si es o no, los archivos que desea analizar lo contienen, y necesito alguna manera de analizarlos. ¿Alguna sugerencia para otro analizador de expatriados, o ajustes para expatriados, que permitirían que haga eso?


Actualización: he descubierto BeautifulSoup hace un momento, un analizador de sopa de etiqueta como se indica más adelante en el comentario respuesta, y para la diversión que regresó a este problema y trató de usarlo como un XML-limpiador en frente de elementtree, pero obedientemente convirtió el &#0; en un solo byte nulo-como-válido. : -)

cleaned_s = StringIO(
  BeautifulStoneSoup('<test><null>&#0;</null><elem3>three</elem3></test>',
                     convertEntities=BeautifulStoneSoup.XML_ENTITIES
  ).renderContents()
)
tree = ElementTree.parse(cleaned_s)

... rendimientos

xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 12

En mi caso particular, sin embargo, no necesita realmente el análisis XPath como tal, podría haber ido con ella misma y su nodo bastante simple adressing parsed_tree.test.elem1.contents[0] estilo BeautifulSoup.

¿Fue útil?

Solución

&#0; no está en el rango de caracteres legales definido por la especificación XML . Por desgracia, mis conocimientos de Python son bastante rudimentarias, así que no soy de mucha ayuda allí.

Otros consejos

&#0; no es un carácter válido XML. Idealmente, usted sería capaz de obtener el creador del archivo para cambiar su proceso de manera que el archivo no era válido como este.

Si tiene que aceptar estos archivos, se les podría pre-procesar a su vez &#0 en otra cosa. Por ejemplo, recoger @ como un carácter de escape, a su vez "@" en "@@", y "&#0;" en "@ 0".

A continuación, a medida que los datos de texto del programa de análisis, se puede invertir el mapeo. Esto es sólo un ejemplo, se puede inventar cualquier sintaxis de escape te gusta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top