c++ - TinyXML - 有什么方法可以跳过有问题的 DOCTYPE 标签吗?

标签 c++ tinyxml

我正在使用 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 ..> 的预处理步骤)?

最佳答案

您可以先将整个文件加载到 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 文件太大,最好使用内存映射文件而不是将整个文件加载到内存中。但这完全是另一个问题。

关于c++ - TinyXML - 有什么方法可以跳过有问题的 DOCTYPE 标签吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19100408/

相关文章:

c++ - 在 C++ 中将定义的结构转换为 double (复数)

c++ - 使用 TinyXml 将 XML 写入 txt 文件

c++ - TinyXML-2 中 `TiXmlNode::FirstChild(const char *)` 的替代项是什么?

c++ - 如何使用tinyxml获取元素的父节点

c++ - 使用 TinyXML 查找特定文本值

c++ - 静态变量可以多次初始化吗?

c++ - 从输入参数具体用例推导出尾随返回类型

c++ - 从 std::copy 和 std::copy_n 中提取输入迭代器

c++ - 当从仿函数类模板参数推导出(衰减)类型时,完美转发失败。为什么?

c++ - 在没有xml文件的情况下使用c++解析tinyXML xml