aplicaciones creadas con python
Error ''no se pudo cargar la entidad externa'' cuando se usa Python lxml (4)
En concierto con lo que dijo mzjn, si desea pasar una cadena a etree.parse (), simplemente envuélvalo en un objeto StringIO.
Ejemplo:
from lxml import etree
from StringIO import StringIO
myString = "<html><p>blah blah blah</p></html>"
tree = etree.parse(StringIO(myString))
Este método se utiliza en la documentación de lxml .
Estoy tratando de analizar un documento XML que recupero de la web, pero se bloquea después de analizar con este error:
'': failed to load external entity "<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="GreenButtonDataStyleSheet.xslt"?>
Esa es la segunda línea en el XML que se descarga. ¿Hay alguna forma de evitar que el analizador intente cargar la entidad externa u otra forma de resolver esto? Este es el código que tengo hasta ahora:
import urllib2
import lxml.etree as etree
file = urllib2.urlopen("http://www.greenbuttondata.org/data/15MinLP_15Days.xml")
data = file.read()
file.close()
tree = etree.parse(data)
Recibes ese error porque el XML que estás cargando hace referencia a un recurso externo:
<?xml-stylesheet type="text/xsl" href="GreenButtonDataStyleSheet.xslt"?>
LXML no sabe cómo resolver GreenButtonDataStyleSheet.xslt
. Probablemente, usted y yo nos demos cuenta de que estará disponible en relación a su URL original, http://www.greenbuttondata.org/data/15MinLP_15Days.xml
... el truco es decirle a lxml
cómo cargarlo.
La documentación de lxml incluye una sección titulada " Carga de documentos y resolución de URL ", que tiene casi toda la información que necesita.
lxml docs para analizar dice Para analizar desde una cadena, use la función fromstring()
lugar.
parse(...)
parse(source, parser=None, base_url=None)
Return an ElementTree object loaded with source elements. If no parser
is provided as second argument, the default parser is used.
The ``source`` can be any of the following:
- a file name/path
- a file object
- a file-like object
- a URL using the HTTP or FTP protocol
To parse from a string, use the ``fromstring()`` function instead.
Note that it is generally faster to parse from a file path or URL
than from an open file object or file-like object. Transparent
decompression from gzip compressed sources is supported (unless
explicitly disabled in libxml2).
etree.parse(source)
espera que la source
sea una de
- un nombre de archivo / ruta
- un objeto de archivo
- un objeto parecido a un archivo
- una URL usando el protocolo HTTP o FTP
El problema es que está suministrando el contenido XML como una cadena.
También puedes hacerlo sin urllib2.urlopen()
. Solo usa
tree = etree.parse("http://www.greenbuttondata.org/data/15MinLP_15Days.xml")
Demostración (usando lxml 2.3.4):
>>> from lxml import etree
>>> tree = etree.parse("http://www.greenbuttondata.org/data/15MinLP_15Days.xml")
>>> tree.getroot()
<Element {http://www.w3.org/2005/Atom}feed at 0xedaa08>
>>>
En una respuesta de la competencia , se sugiere que lxml falla debido a la hoja de estilo a la que hace referencia la instrucción de procesamiento en el documento. Pero ese no es el problema aquí. lxml no intenta cargar la hoja de estilo, y el documento XML se analiza bien si lo hace como se describe anteriormente.
Si realmente quieres cargar la hoja de estilo, debes ser explícito al respecto. Se necesita algo como esto:
from lxml import etree
tree = etree.parse("http://www.greenbuttondata.org/data/15MinLP_15Days.xml")
# Create an _XSLTProcessingInstruction object
pi = tree.xpath("//processing-instruction()")[0]
# Parse the stylesheet and return an ElementTree
xsl = pi.parseXSL()