web-dev-qa-db-fra.com

Erreur 'impossible de charger l'entité externe' lors de l'utilisation de Python lxml

J'essaie d'analyser un document XML que je récupère sur le Web, mais il se bloque après l'analyse avec cette erreur:

': failed to load external entity "<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="GreenButtonDataStyleSheet.xslt"?>

C'est la deuxième ligne du XML qui est téléchargée. Existe-t-il un moyen d’empêcher l’analyseur d’essayer de charger l’entité externe ou un autre moyen de résoudre ce problème? C'est le code que j'ai jusqu'à présent:

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)
18
daveeloo

En accord avec ce que mzjn a dit, si vous voulez passer une chaîne à etree.parse (), enroulez-la simplement dans un objet StringIO.

Exemple:

from lxml import etree
from StringIO import StringIO

myString = "<html><p>blah blah blah</p></html>"

tree = etree.parse(StringIO(myString))

Cette méthode est utilisée dans la documentation lxml .

21
kevin

etree.parse(source) s'attend à ce que source soit l’un des

  • un nom de fichier/chemin
  • un objet de fichier
  • un objet de type fichier
  • une URL utilisant le protocole HTTP ou FTP

Le problème est que vous fournissez le contenu XML sous forme de chaîne. 

Vous pouvez également vous passer de urllib2.urlopen(). Juste utiliser

tree = etree.parse("http://www.greenbuttondata.org/data/15MinLP_15Days.xml")

Démonstration (en utilisant 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>
>>>   

Dans un réponse concurrente , il est suggéré que lxml échoue en raison de la feuille de style référencée par l'instruction de traitement dans le document. Mais ce n'est pas le problème ici. lxml n'essaie pas de charger la feuille de style et le document XML est analysé correctement si vous procédez comme décrit ci-dessus.

Si vous voulez réellement charger la feuille de style, vous devez être explicite à ce sujet. Quelque chose comme ceci est nécessaire:

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()   
11
mzjn

documents lxml pour parse dit Pour analyser une chaîne, utilisez plutôt la fonction fromstring().

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).
1
jrwren

Vous obtenez cette erreur car le XML que vous chargez fait référence à une ressource externe:

<?xml-stylesheet type="text/xsl" href="GreenButtonDataStyleSheet.xslt"?>

LXML ne sait pas comment résoudre GreenButtonDataStyleSheet.xslt. Vous et moi-même réalisons probablement qu'il sera disponible par rapport à votre URL d'origine, http://www.greenbuttondata.org/data/15MinLP_15Days.xml... l'astuce consiste à dire à lxml comment s'y prendre pour le charger.

La documentation lxml comprend une section intitulée " Chargement de document et résolution d'URL ", qui contient à peu près toutes les informations dont vous avez besoin.

0
larsks