Что такое парсер XML?Использование Экспата
-
03-07-2019 - |
Вопрос
Это может показаться простым вопросом.
Но я искал синтаксический анализатор XML для использования в одном из моих приложений, работающих в Linux.
Я использую Эмигрант и проанализировал мой XML-файл, прочитав его.Однако выход такой же, как и вход.
Это мой файл, который я читаю:
<?xml version="1.0" encoding="utf-8"?>
<books>
<book>
<id>1</id>
<name>Hello, world!</name>
</book>
</books>
Однако после того, как я это прошёл, я получаю точно то же самое, что и результат.Это заставляет меня задаться вопросом, для чего нужен парсер?
Еще одна вещь.Я использую Экспат.Что кажется довольно сложным в использовании.Мой код ниже:Это читается в файле.Но моему приложению придется парсить буфер, который будет получен сокетом, а не из файла.Есть ли у кого-нибудь образцы этого?
int parse_xml(char *buff)
{
FILE *fp;
fp = fopen("mybook.xml", "r");
if(fp == NULL)
{
printf("Failed to open file\n");
return 1;
}
/* Obtain the file size. */
fseek (fp, 0, SEEK_END);
size_t file_size = ftell(fp);
rewind(fp);
XML_Parser parser = XML_ParserCreate(NULL);
int done;
memset(buff, 0, sizeof(buff));
do
{
size_t len = fread(buff, 1, file_size, fp);
done = len < sizeof(buff);
if(XML_Parse(parser, buff, len, done) == XML_STATUS_ERROR)
{
printf("%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)),
XML_GetCurrentLineNumber(parser));
return 1;
}
}
while(!done);
fclose(fp);
XML_ParserFree(parser);
return 0;
}
Решение
Мне потребовалось некоторое время, чтобы разобраться в синтаксическом анализе XML (хотя я делаю это на Perl, а не на C).По сути, вы регистрируете функции обратного вызова.Анализатор будет проверять ваш обратный вызов для каждого узла и передавать структуру данных, содержащую все виды важных битов (например, открытый текст, любые атрибуты, дочерние узлы и т. д.).Вам необходимо поддерживать какую-то информацию о состоянии — например, хэш-дерево, в которое вы подключаете данные, или строку, содержащую всю информацию, но не содержащую XML.
Просто помните, что XML не является линейным, и нет смысла анализировать его как длинный кусок текста.Вместо этого вы анализируете его как дерево.Удачи.
Другие советы
Expat — парсер с четным управлением.Вам нужно написать код для работы с тегами, атрибутами и т. д.а затем зарегистрируйте код в парсере.Есть статья здесь где описано, как это сделать.
Что касается чтения из сокета, в зависимости от вашей платформы вы можете обращаться с сокетом как с дескриптором файла.В противном случае вам придется выполнить собственное чтение из сокета, а затем явно передать данные экспату.Для этого существует API.Однако я бы сначала попробовал заставить его работать с обычными файлами.
Вместо expat вы можете взглянуть на libxml2, который, вероятно, уже включен в ваш дистрибутив.Он намного мощнее, чем экспат, и дает вам массу вкусностей:DOM (режим дерева), SAX (режим потоковой передачи), XPath (незаменим для выполнения чего-либо сложного с XML, ИМХО) и многое другое.Он не такой легкий, как Expat, но его намного проще использовать.
Итак, вы выбрали самый сложный парсер XML (с парсерами, управляемыми событиями, работать сложнее).Почему экспат, а не библиотека libxml?