我工作的应用程序使用XML进行保存/恢复。这是一个示例代码段:
<?xml version="1.0" standalone="yes"?>
<itemSet>
<item handle="2" attribute1="30" attribute2="blah"></item>
<item handle="5" attribute1="27" attribute2="blahblah"></item>
</itemSet>
我希望能够有效地预处理我从配置文件中读入的XML。特别是,我想从上面的示例配置中提取句柄值。
理想情况下,我需要一个函数/方法来传递不透明的XML字符串,并返回列表中的所有句柄值。对于上面的示例,将返回包含2和5的列表。
我知道有一个正常的表达会有所帮助,但这是最有效的方法吗?字符串操作代价很高,而且我可能需要在配置文件中处理1000个XML字符串。
答案 0 :(得分:4)
您正在寻找一种面向流的XML解析器,它一次读取XML中的每个节点,而不是将整个节点加载到内存中。
其中最着名的是SAX - Simple API for XML
这是一个good article,描述了为什么要使用SAX以及在C ++中使用SAX的具体内容。
您可以将SAX视为XML的解析器,它只将最小值加载到内存中,因此适用于非常大的XML文档。与Regex或DOM方法相比,它需要您将整个文档加载到内存中。
答案 1 :(得分:0)
我猜某种类型的正则表达式将是您提高效率的最佳选择。它比将XML解析为任何类型的结构构造要快,只要您能够在一次传递中提取所需的所有信息,它就可能是最有效的方法。
答案 2 :(得分:0)
很难打败像:
/* untested code */
using std::string;
size_t pos = 0;
vector<int> handles;
while ((pos = xmlstr.find("handle=\"", pos)) != string::npos) {
handles.push_back(atoi(xmlstr.data() + pos + 7));
}
如果使用适当的大小调用handles.reserve()
,或者如果handles
是deque
或list
,则会更有效,具体取决于它是如何需要的以后用过。如果xml字符串可能格式不正确(xmlstr.data()
不是以空值终止,那么这是不安全的代码,因此atoi
可能不在数组的末尾)。它也不会检查handle
是否不是较长属性名称的结尾,或者实际上它是否是属性。
将正则表达式用于"\\bhandle=\"\\d+\""
之类的正则表达式可能会使得结果几乎同样快,并且错误的可能性更小。它仍然不能确认句柄是属性;你必须判断这是否可能是一个问题。