从XML中提取特定数字属性的有效方法

时间:2009-02-16 04:20:06

标签: c++ xml regex performance

我工作的应用程序使用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字符串。

3 个答案:

答案 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(),或者如果handlesdequelist,则会更有效,具体取决于它是如何需要的以后用过。如果xml字符串可能格式不正确(xmlstr.data()不是以空值终止,那么这是不安全的代码,因此atoi可能不在数组的末尾)。它也不会检查handle是否不是较长属性名称的结尾,或者实际上它是否是属性。

将正则表达式用于"\\bhandle=\"\\d+\""之类的正则表达式可能会使得结果几乎同样快,并且错误的可能性更小。它仍然不能确认句柄是属性;你必须判断这是否可能是一个问题。