2012-05-04 25 views
14

Tôi đang cố gắng để phân tích một tài liệu XML tôi lấy từ trang web, nhưng nó bị treo sau khi phân tích với lỗi này:Lỗi 'không thể tải thực thể bên ngoài' khi sử dụng Python lxml

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

Đó là lần thứ hai dòng trong XML được tải xuống. Có cách nào để ngăn trình phân tích cú pháp cố gắng tải thực thể bên ngoài hay cách khác để giải quyết vấn đề này không? Đây là mã tôi có cho đến nay:

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) 

Trả lời

0

Bạn đang nhận lỗi rằng vì XML bạn đang tải tài liệu tham khảo một nguồn tài nguyên bên ngoài:

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

lxml không biết làm thế nào để giải quyết GreenButtonDataStyleSheet.xslt . Bạn và tôi có thể nhận ra rằng nó sẽ có sẵn liên quan đến URL ban đầu của bạn, http://www.greenbuttondata.org/data/15MinLP_15Days.xml ... mẹo là để nói cho lxml cách tải về nó.

lxml documentation bao gồm một phần có tiêu đề "Document loading and URL resolving", có tất cả thông tin bạn cần.

+0

Bạn có biết liệu có thể tắt tải tất cả tài nguyên bên ngoài không? Tôi nhìn vào tài liệu nhưng không thể tìm thấy gì cả. – daveeloo

+1

"* Bạn nhận được lỗi đó vì XML bạn đang tải tài liệu bên ngoài *". Đó không phải là lý do bạn gặp lỗi. Xin vui lòng xem câu trả lời của tôi. – mzjn

9

etree.parse(source) hy vọng source là một trong

  • một tên tập tin/path
  • một đối tượng tập tin
  • một tập tin giống như đối tượng
  • URL bằng cách sử dụng HTTP hoặc FTP protocol

Vấn đề là bạn đang cung cấp nội dung XML dưới dạng chuỗi.

Bạn cũng có thể thực hiện mà không cần urllib2.urlopen(). Chỉ cần sử dụng

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

Demonstration (sử dụng 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> 
>>> 

Trong một competing answer, nó được gợi ý rằng lxml thất bại vì các kiểu tham chiếu bởi hướng dẫn xử lý trong tài liệu . Nhưng đó không phải là vấn đề ở đây. lxml không cố tải biểu định kiểu và tài liệu XML được phân tích cú pháp tốt nếu bạn làm như mô tả ở trên.

Nếu bạn thực sự muốn tải biểu định kiểu, bạn phải rõ ràng về nó. Một cái gì đó như thế này là cần thiết:

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() 
+0

Downvoter: hãy giải thích những gì là sai với câu trả lời này. – mzjn

+0

cảm ơn bạn mzjn. bạn đúng rồi! upvoted. – Duke

+0

@Duke: Cảm ơn bạn! Thật tuyệt khi cuối cùng cũng nhận được một số phản hồi tích cực. – mzjn

18

Trong buổi hòa nhạc với những gì mzjn nói, nếu bạn muốn vượt qua một chuỗi để etree.parse(), chỉ cần quấn nó trong một đối tượng StringIO.

Ví dụ:

from lxml import etree 
from StringIO import StringIO 

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

tree = etree.parse(StringIO(myString)) 

Phương pháp này được sử dụng trong lxml documentation.

+3

Đối với python3: 'từ io nhập StringIO' – Adversus

1

tài liệu lxml để phân tích cú pháp nói Để phân tích cú pháp từ chuỗi, hãy sử dụng hàm fromstring() thay thế.

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). 
Các vấn đề liên quan