Ошибка при загрузке внешнего объекта при использовании Python lxml
Я пытаюсь проанализировать XML-документ, который я извлекаю из Интернета, но он сработает после разбора этой ошибки:
': failed to load external entity "<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="GreenButtonDataStyleSheet.xslt"?>
Это вторая строка в загружаемом XML. Есть ли способ предотвратить попытки парсера загрузить внешний объект или другой способ решить эту проблему? Это код, который у меня есть до сих пор:
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)
Ответы
Ответ 1
В согласии с тем, что сказал 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.
Ответ 2
etree.parse(source)
ожидает, что source
будет одним из
- имя файла/путь
- файловый объект
- файловый объект
- URL-адрес с использованием протокола HTTP или FTP
Проблема заключается в том, что вы поставляете 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()
Ответ 3
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).
Ответ 4
Вы получаете эту ошибку, потому что загружаемый XML ссылается на внешний ресурс:
<?xml-stylesheet type="text/xsl" href="GreenButtonDataStyleSheet.xslt"?>
LXML не знает, как разрешить GreenButtonDataStyleSheet.xslt
. Мы с вами, вероятно, понимаем, что он будет доступен по отношению к вашему исходному URL-адресу, http://www.greenbuttondata.org/data/15MinLP_15Days.xml
... трюк заключается в том, чтобы сообщить lxml
, как его загрузить.
Документация lxml включает раздел под названием " Загрузка документа и разрешение URL-адреса ", который имеет практически всю необходимую информацию.