2010-10-06 72 views
3

我有一個生成NewsML類型XML文件的工具,我想在生成文件後驗證它們。 我收到一個錯誤:使用DTD驗證XML無法使用lxml導入實體

Attempt to load network entity http://www.w3.org/TR/ruby/xhtml-ruby-1.mod

蟒蛇電話是:

parser = etree.XMLParser(load_dtd=True, dtd_validation=True) 
treeObject = etree.parse(f, parser) 

首先我不知道如果我需要兩個 「load_dtd =真,dtd_validation =真」,但我反正使用它。 二錯誤似乎是從被定義爲進口NITF-3-4.dtd未來:

<!ENTITY % xhtml-ruby.mod PUBLIC 
    "-//W3C//ELEMENTS XHTML Ruby 1.0//EN" "http://www.w3.org/TR/ruby/xhtml-ruby-1.mod"> 
%xhtml-ruby.mod; 

將限於lxml出去檢索此XHTML的紅寶石1.mod或我有所有的DTD文件在本地。

回答

4

嘗試使用no_network=False構建解析器。正如指出的documentation

no_network - prevent network access when looking up external documents (on by default)

進口DTD模塊應該由LXML得到恢復,但如果不允許網絡訪問,將不能夠做到這一點(不記入文檔本身,只爲加載外部引用的文檔。事實上,我希望你加載dtd本身時會出錯,所以我認爲文檔引用了該dtd的本地可用副本,並且它只是引用遠程資源的dtd本身?)

你也可以使用一個目錄來使用本地可用的副本(不僅可以繞過這個問題,而且可以更高效,更友好地向w3c服務器發送;-))。 libxml2的(按LXML使用)會爲您在/etc/xml/catalog目錄是否存在等,以及XML_CATALOG_FILES環境變量(見Libxml2 docs

(還可以編寫自己的resolvers爲LXML攔截和處理請求,但在這種情況下可能會過度)

請注意,除解析時間驗證外,還有另一個選項:使用DTD class單獨加載dtd,並將​​其用作驗證程序。

這將驗證與所提供的DTD解析文檔無論哪個DTD(如果有的話)是由DOCTYPE聲明引用(它可以很方便:不是每一個有效的XML文件一定是有效的根據DTD 想) 。

因爲dtd只需要檢索和解析一次,如果你正在驗證大量文檔,這應該會更快),(如果我沒有弄錯),你將不會遇到no_network問題。

接近的另一個好處是:你甚至可以在序列化之前驗證元素/元素樹(如果你的生成工具使用lxml)。

最後說明:如果您有權訪問解析時的dtd(無法解析的實體...),則只能解析某些文檔。如果可以的話,避免這種情況。 (儘管不是每個人都會同意:如果可能的話,完全避免doctype聲明)。