我似乎无法让libxml2从内存中正确解析DTD:DTD包含对指向w3c.org的外部XHTML实体的引用。链接正常,浏览器加载它们的内容就好了。但是,即使从xmlIOParseDTD
函数返回成功状态,libxml2也会报告无法加载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
文件可以从这里下载:http://xml.evernote.com/pub/enml2.dtd
构建(在我的情况下在Linux上):
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的错误。
答案 0 :(得分:0)
问题似乎不在libxml2中,而是在w3c站点中,相关dtd文件中的外部实体使用该引用。有关详细信息,请参见类似the answer的question。我通过从浏览器链接下载.ent
文件并将其全部内容包含在dtd文件而不是引用中来解决问题。