web-dev-qa-db-ja.com

Python lxmlを使用すると、「外部エンティティのロードに失敗しました」というエラー

Webから取得したXMLドキュメントを解析しようとしていますが、次のエラーで解析後にクラッシュします。

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

これは、ダウンロードされるXMLの2行目です。パーサーが外部エンティティをロードしようとするのを防ぐ方法、またはこれを解決する別の方法はありますか?これは私がこれまでに持っているコードです:

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

Mzjnの発言に合わせて、etree.parse()に文字列を渡したい場合は、StringIOオブジェクトにラップするだけです。

例:

from lxml import etree
from StringIO import StringIO

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

tree = etree.parse(StringIO(myString))

このメソッドは lxmlドキュメント で使用されます。

23
kevin

etree.parse(source)source

  • ファイル名/パス
  • ファイルオブジェクト
  • ファイルのようなオブジェクト
  • hTTPまたはFTPプロトコルを使用したURL

問題は、XMLコンテンツを文字列として提供していることです。

urllib2.urlopen()なしでも実行できます。使うだけ

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

デモ(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>
>>>   

競合する回答 では、ドキュメントの処理命令によって参照されるスタイルシートが原因でlxmlが失敗することが推奨されます。しかし、それはここでは問題ではありません。 lxmlはスタイルシートをロードしようとせず、上記のように実行すると、XMLドキュメントは正常に解析されます。

スタイルシートを実際にロードする場合は、明示的にする必要があります。このようなものが必要です:

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

lxml docs for parseは言う文字列から解析するには、代わりに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).
2
jrwren

ロードしているXMLが外部リソースを参照しているため、このエラーが発生します。

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

LXMLはGreenButtonDataStyleSheet.xsltを解決する方法を知りません。あなたと私はおそらく、それが元のURL http://www.greenbuttondata.org/data/15MinLP_15Days.xml...に関連して利用可能になることを理解しているでしょう。トリックはlxmlにロード方法を伝えることです。

lxml documentation には、「 Document loading and URL resolving 」というタイトルのセクションが含まれており、必要な情報がほぼすべて含まれています。

0
larsks