LINUX.ORG.RU

Релиз libxml - читалка xml файлов

 ,


0

2

libxml 1.0 - читалка xml файлов. Отличается от других xml библиотек тем, что в этой библиотеке все объекты хранятся в односвязном списке. В первой версии не так много функций, но библиотека может читать простые xml файлы. На github находиться туториал, в котором описываются все возможности библиотеки. ссылка

Из всех зверств и непотребств в коде мне больше всего понравилось использование setjmp/longjmp вместо возврата кода ошибки.

А какое ваше любимое место?

i-rinat ★★★★★ ()

libxml2 для продакшена, asmxml для лулзов и маломощных устройств, expat для некрофилов, а это для чего? хотя бы уровень libxml2 вытянет?

anonymous ()
Ответ на: комментарий от anonymous

хотя бы уровень libxml2 вытянет?

Незнаю, нет. Но я так и не понел как в libxml2 получать атрибуты. Также не удобно искать вложенные объекты. Приходиться писать вот такой код

#include <libxml/tree.h>
#include <libxml/parser.h>
#include <stdio.h>
#include <string.h>

int main () 
{
	xmlDoc *document, *doc;
	xmlNode *root, *first_child, *node, *i, *e, *text;
	xmlNodePtr n;
	char *filename = "file.xml";
	xmlInitParser ( );
	document = xmlReadFile ( filename, NULL, 0 );
	root = xmlDocGetRootElement ( document );
	first_child = root->children;
	n = xmlStringGetNodeList ( doc, "food" );
	for ( node = first_child; node; node = node->next ) {
		if ( !strncmp ( node->name, "food", 4 ) ) {
			i = node->children;
			for ( e = i; e; e = e->next ) {
				if ( !strncmp ( e->name, "text", 4 ) ) continue;
				printf ( "%s = ", e->name );
				text = e->children;
				for ( text = e->children; text; text = text->next )
					printf ( "%s", text->content );
				printf ( "\n" );
			}
		}
	}
}
И это только чтобы во внутренние объекты залесть. Но может есть и более удобный способ. Но моя либа полегче в освоении, да и я знаю как получить нужную информацию.

ghost_of_the_west ()
Ответ на: комментарий от ghost_of_the_west

Ну типа того, только ты можешь взять, скажем, тот же xpath и быть в шоколаде. Вообще, код должен выглядеть немного не так, но примерно то и есть. Там всё на структурках.

Можешь ещё поискать вдохновения тут, если тебе си не нравится чем-то https://pugixml.org/

anonymous ()
#include "xml.h"
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    system("GET https://www.linux.org.ru/forum/development/14646344?lastmod=1543800678205#comment-14646429 > test.xml ");
    struct xmlnode *node = read_xml_file ( "test.xml" );
    struct xmlnode *n = find_object_xml ( node, "title" );
    printf ( "[TITLE]  %s\n", get_content ( n ) );
    n = find_object_xml ( node, "h2" );
    printf ( "[H2]  %s\n", get_content ( n ) );
    n = find_object_xml ( node, "div" );
    printf ( "[DIV]  %s\n", get_content ( n ) );
    n = find_object_xml ( node, "head" );
    printf ( "[DIV]  %s\n", get_content ( n ) );


    return 0;
}

У тебя пдразумевается возможность html обрабатывать

dron@gnu:~/libxml$ gcc test.c xml.c -o exe; ./exe
[TITLE]  Релиз libxml - читалка xml файлов  — Development — Форум
[H2]  Похожие темы
[DIV]  
Ошибка сегментирования
dron@gnu:~/libxml$ 

Чини.

linux-org-ru ()
Ответ на: комментарий от ghost_of_the_west

И да по поводу API

do_object_postfix(); -> find_object_xml();

как по мне лучше:

prefix_object_do();  -> xml_object_find();

или 

prefix_do_object();  -> xml_find_object();

Обычно когда юзают в проекте десятки библиотек очень удобно что у api есть префиксы (gtk/curl/kore/), как для автодополнения, так и для поиска в целом. Когда наименования функций с предположением что api маленькое и его просто нужно запомнить хреново выходит. Но дело твоё я так, к слову.

linux-org-ru ()
Ответ на: комментарий от linux-org-ru

Проблема вот в чём, парсер пытается прочитать этот тег <html lang=ru>, из-за чего он сбивается, в нормальном xml формате было бы так <html lang="ru">. Думаешь стоит это добавить? html формат немного отличается от xml, в нем например meta является на одном уровне, в нем не должно быть вложенных объектов, если в html meta пишется на одном уровне так <meta>, то в xml она бы писалась так <meta/>.

ghost_of_the_west ()
Ответ на: комментарий от ghost_of_the_west

html формат немного отличается от xml

Ну это как бы вообще разные вещи, просто похожие https://habr.com/post/252283/

Думаешь стоит это добавить?

Ты либо бери и вкуривай https://www.opennet.ru/docs/RUS/XML/ и потом дописывай свою библиотеку которая будет для xml и всё иное будет считать не валидным и выходить.

Либо делай комбайн xml/xhtml/html там нюансов тонна.

Весь современный веб пишет и генерит html с ошибками, просто в них парсеры/думеры ужасно сложные и могут это определить и тупо проигнорировать отобразив правильно. А вообще задача нетривиальная, я бы вот так сесть и написать надёжную чисто xml или html не смог. Сядь и покрой свой код тонной тестов и решай проблемы возникшие.

linux-org-ru ()
Ответ на: комментарий от linux-org-ru

При парсинге html, наиболее сложной проблемой является восстановление пропущенных закрывающихся тегов. Насколько я помню, до стандарта html5 там творился треш и угар: каждый браузер это делал по-своему, в зависмости от его версии, режима совместимости и т.д. С html5 появился внятное стандартное поведение, но я не знаю, можно ли его раелизовать в sax парсерах, без полного построения dom.

Я особо в код этой библиотеки не вчитывался, но, судя по всему, это не dom парсер (т.е. не будет возможности перехода к конкретному узлу не за линейное время) и не нормальный sax парсер, т.к. требует полностью заполненный буфер с содержимым всего xml. + как минимум, буфер с содержимым самого xml статический, т.е. с этой либой нельзя пареллельно работать в нескольких потоках. В общем, поделка достойная универской лабораторки. За опенсорсный проект плюс, но смысла в этом проекте полный ноль.

while ( array[index_xml] == 10 ) index_xml++; я так и не понял почему именно 10

Это скорее всего, символ переноса строки '\n'. Кто-то не только стандарт xml не читал, но и книжки по C.

dr15 ()
Ответ на: комментарий от linux-org-ru

Это я вместо if ( array[index_xml] == 10 ) index_xml++ использую, потому как if проверяет один символ. Проверяет он перенос строки, и так пока не пройдет перенос строки. Но это вроде даже и не надо выполнять, потому как там и так всё сработает, я на всякий случай добавил такую конструкцию.

ghost_of_the_west ()
Ответ на: комментарий от dr15

но смысла в этом проекте полный ноль.

Да чтой то, этот парень тут известен хорошо))) Пилит всякое, учится потихоньку. Ацки велосипедит ))) И заставляет нас переодически компилять по фану его софтинки. Пускай химичит, ему в кайф и это хорошо. А там что будет то будет

linux-org-ru ()
Ответ на: комментарий от ghost_of_the_west

А как бы ты сделал? Насчет не за линейное время

Почитай про dom парсеры. На первом этапе при парсинге строится dom модель xml документа в виде дерева и затем навигация по этому дереву происходит с той скоростью, которая тебе нужна. Из плюсов, обычно это дерево можно еще и модифицировать, а затем преобразовать опять в текстовый xml. Из минусов - документ должен полностью содержаться в памяти + дополнительное время на построение дерева.

За опенсорсный проект плюс, но смысла в этом проекте полный ноль.

Хотя не, никакого плюса в карму. За setjmp нужно руки отрывать, особенно в таком виде. В данном случае его использование абсолютно ничем не обоснованно. Ну и плюс обычные проблемы с отсутвием проверок ошибок работы с файлами.

while ( array[index_xml] == 10 ) index_xml++;
while ( array[index_xml] == ' ' ) index_xml++;
while ( array[index_xml] == 10 ) index_xml++;

А если там будет стоять пробел, перенос строки, пробел, перенос строки? И знак табуляции (9 код) и знак возврата коретки (13) не являются пробельными символами? Все же иногда нужно читать спецификации.

dr15 ()
Ответ на: комментарий от dr15

А как ты тогда обратишься к объекту, который вложен в другой объект, которые вложен в другой, и так например три раза. Будешь писать так?

a = node->children;
for ( ; a; a = a->next ) {
  b = a->children;
    for ( ; b; b = b->next ) {
      c = b->children;
        for ( ; c; c = c->next ) {
          printf ( "%s\n", c->content );
        }
    }
}
Ну как ты будешь это делать, это я пример привел из libxml2, как к элементам обращаться. Да я незнаю всех фукнций, и может быть есть более удобный способ, но я его незнаю. Также я не смог реализовать так, чтобы к вложенному объекту можно было обратиться по children. Да потом это все усложняет. Я упростил, и примеры есть на github. Там хоть и односвязная структура, но зато можно обратиться к любому элементу на любом уровне. Можно также варьировать, если надо только на нулевом уровне искать объекты, то будут отображаться только с нулевым уровнем, но поиск будет по списку вперед идти. Я думаю что ты мне хочешь дать понять что ты разбираешься в xml, может покажешь как в libxml2 можно получить доступ к объекту за не линейное время?

ghost_of_the_west ()

Отличается от других xml библиотек тем, что в этой библиотеке все объекты хранятся в односвязном списке

Есть ли объективная причина использовать список вместо нормального дерева?

XMs ★★★★ ()
Ответ на: комментарий от XMs

Да, упростить поиск. Ну давай, покажи мне пример на любой либе ( кроме моей ), попробуй получить все name, которые есть в этом файле. Напиши код, и сравним, где быстрее будет и по памяти тоже сравним, если это возможно. Пример файла будет простой.

<?xml version="1.0" encoding="UTF-8" ?>
<breakfast-menu>
  <food>
    <name>Belgian Waffles</name>
    <price>$5.95</price>
    <description>two of our famous Belgian Waffles with plenty of real maple syrup</description>
    <calories>650</calories>
  </food>
  <food>
    <name>Strawberry Belgian Waffles</name>
    <price>$7.95</price>
    <description>light Belgian waffles covered with strawberrys and whipped cream</description>
    <calories>900</calories>
  </food>
  <food>
    <name>Berry-Berry Belgian Waffles</name>
    <price>$8.95</price>
    <description>light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
    <calories>900</calories>
  </food>
  <food>
    <name>French Toast</name>
    <price>$4.50</price>
    <description>thick slices made from our homemade sourdough bread</description>
    <calories>600</calories>
  </food>
  <food>
    <name>Homestyle Breakfast</name>
    <price>$6.95</price>
    <description>two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
    <calories>950</calories>
  </food>
</breakfast-menu>
Ты напишешь свой вариант, а я свой.

ghost_of_the_west ()

Может быть, это и нужно, но... Очччень неудачное название, у 99% тех, кому это нужно, будет ассоциироваться с чем-то вроде предка libxml2. Можно было бы назвать как-нибудь вроде tinyxml, хотя... oh, shit... Ну я не знаю, nanoxml какой-нибудь...

hobbit ★★★★★ ()
Ответ на: комментарий от ghost_of_the_west

Побольше и почаще. Возьми 100 файлов в секунду для начала (1мб), подними до 1000, 10000, 100000.

Это реальные юзкейсы для всех этих парсеров. Потом начни разбирать невалидные и со сложными структурами, посмотри на производительность и универсальность.

anonymous ()