我正在使用TinyXML2来解析看起来有点像的XML:
<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE comp PUBLIC "-//JWS//DTD xyz//EN" "file:/documentum/xyz.dtd"
[<!ENTITY subject SYSTEM "dctm://he/abc">
]>
<comp>
...
</comp>
不幸的是,根据http://www.grinninglizard.com/tinyxmldocs/,看起来TinyXML不支持解析DOCTYPE标记,例如上面示例中的标记。我对DTD本身不感兴趣,只想解析XML的其余部分(从<comp>
标记开始)。推荐或最佳方法是什么?我尝试检索以<comp>
为根的XML子树(使用document.FirstChildElement("comp")
),但这种方法失败了,可能是因为TinyXML无法继续解析超出<!ENTITY
标记,它似乎认为是错误。关于如何使用TinyXML本身实现这一点的任何想法(即,最好不需要在调用TinyXML之前使用正则表达式匹配删除<!DOCTYPE ..>
的预处理步骤)?
答案 0 :(得分:1)
您可以先将整个文件加载到std :: string中,跳过不支持的语句,然后解析生成的文档,如下所示:
// Open the file and read it into a vector
std::ifstream ifs("filename.xml", std::ios::in | std::ios::binary | std::ios::ate);
std::ifstream::pos_type fsize = ifs.tellg();
ifs.seekg(0, ios::beg);
std::vector<char> bytes(fsize);
ifs.read(&bytes[0], fsize);
// Create string from vector
std::string xml_str(&bytes[0], fsize);
// Skip unsupported statements
size_t pos = 0;
while (true) {
pos = xml_str.find_first_of("<", pos);
if (xml_str[pos + 1] == '?' || // <?xml...
xml_str[pos + 1] == '!') { // <!DOCTYPE... or [<!ENTITY...
// Skip this line
pos = xml_str.find_first_of("\n", pos);
} else
break;
}
xml_str = xml_str.substr(pos);
// Parse document as usual
TiXmlDocument doc;
doc.Parse(xml_str.c_str());
附加说明:如果XML文件太大,最好使用内存映射文件,而不是将整个文件加载到内存中。但这完全是另一个问题。