的libxml2:xmlIOParseDTD:I/O警告:加载失败HTTP资源
问题描述:
我似乎无法得到的libxml2正确地从内存解析DTD:DTD中包含指向w3c.org外部XHTML实体引用。链接正在工作,浏览器加载他们的内容就好了。但是,即使从xmlIOParseDTD
函数返回成功状态,libxml2也会报告加载HTTP资源失败。的libxml2:xmlIOParseDTD:I/O警告:加载失败HTTP资源
下面是最小的测试来重现问题:
#include "libxml/xmlreader.h"
#include <string>
#include <fstream>
#include <iostream>
int main()
{
// Read DTD from file
std::ifstream f;
f.open("enml2.dtd");
if (!f.is_open()) {
std::cerr << "Can't open enml2.dtd file" << std::endl;
return 1;
}
std::string enml;
std::string line;
while(getline(f, line))
{
enml += line;
}
f.close();
// Init parser options
xmlInitParser();
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
// Parse DTD from memory
xmlParserInputBufferPtr pBuf = xmlParserInputBufferCreateMem(enml.c_str(), enml.size(),
XML_CHAR_ENCODING_UTF8);
if (!pBuf) {
std::cerr << "can't allocate input buffer for dtd validation" << std::endl;
return 2;
}
xmlDtdPtr pDtd = xmlIOParseDTD(NULL, pBuf, XML_CHAR_ENCODING_UTF8);
if (!pDtd) {
std::cerr << "can't parse dtd from buffer" << std::endl;
return 3;
}
std::cout << "Successfully parsed DTD" << std::endl;
xmlFreeDtd(pDtd);
return 0;
}
所提到的enml2.dtd
文件可以从这里下载:(在我的情况在Linux上)http://xml.evernote.com/pub/enml2.dtd
体形:
g++ -I/usr/include/libxml2 main.cpp -o libxml2-test -lxml2
运行:
./libxml2-test
I/O warning : failed to load HTTP resource
n 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">%HTMLlat1;
^
%HTMLlat1;
^
I/O warning : failed to load HTTP resource
for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">%HTMLsymbol;
^
%HTMLsymbol;
^
I/O warning : failed to load HTTP resource
for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">%HTMLspecial;
^
%HTMLspecial;
^
Successfully parsed DTD
的libxml2的使用的版本是2.9.1+dfsg1-3ubuntu4.4
,我对Linux Mint的17(对应到Ubuntu 14.04)。
更新:我在OS X 10.9上观察与libxml2 2.9.0相同的东西。此外,xmllint
命令行实用程序无法以与示例代码完全相同的方式获取这些外部条目,即使我使用--loaddtd
选项显式允许获取外部DTD。要么我真的错过了它应该如何工作,或者我遇到了libxml2的错误。
答
它出现的问题是不是在libxml2的,但是在W3C的网站上的参考,其在相关的DTD文件使用的外部实体。更多的细节可以在the answer找到类似的question。我通过从浏览器的链接下载.ent
文件并将其全部内容包括在dtd文件中而不是引用中来解决问题。