Эффективный способ извлечения определенных числовых атрибутов из XML - PullRequest
1 голос
/ 16 февраля 2009

Приложение, которое я работаю, использует 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, который я прочитал из файла конфигурации. В частности, я хочу извлечь значения handle из приведенного выше примера конфигурации.

В идеале мне нужна функция / метод, чтобы можно было передавать непрозрачную строку XML и возвращать все значения дескриптора в списке. Для приведенного выше примера будет возвращен список, содержащий 2 и 5.

Я знаю, что есть регулярное выражение, которое поможет, но это самый эффективный способ сделать это? Манипулирование строками может быть дорогостоящим, и потенциально могут быть тысячи строк XML, которые мне нужно обработать в файле конфигурации.

Ответы [ 3 ]

4 голосов
/ 16 февраля 2009

Вы ищете потоково-ориентированный синтаксический анализатор XML, который читает каждый узел в вашем XML по одному, а не загружает все это в память.

Одним из самых известных является SAX - простой API для XML

Вот хорошая статья , описывающая, почему использовать SAX, а также особенности использования SAX в C ++.

Вы можете думать о SAX как о синтаксическом анализаторе XML, который загружает только минимальный объем в память и хорошо работает с очень большими документами XML. По сравнению с подходом Regex или DOM, который потребует загрузки всего документа в память.

0 голосов
/ 16 февраля 2009

Было бы трудно победить что-то вроде:

/* 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+\"", вероятно, даст вам результаты почти так же быстро, с меньшей вероятностью ошибки. Это все еще не подтверждает, что дескриптор является атрибутом; Вы должны судить, может ли это быть проблемой.

0 голосов
/ 16 февраля 2009

Я думаю, что какое-то регулярное выражение будет вашим лучшим вариантом для эффективности. Это будет быстрее, чем синтаксический анализ XML в любой структурной конструкции, и если вы сможете извлечь всю информацию, которая вам понадобится за один проход, это, вероятно, самый эффективный метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...