Autor Wątek: [c++] echo - parser xml/html  (Przeczytany 3377 razy)

Offline Rokuzo

  • Użytkownik
    • Masz na sprzedaż klucze do cs go?

  • +3
# Październik 19, 2012, 01:42:13
Witam wszystkich forumowiczów.
Odrazu zaznaczam, że nie wiedziałem gdzie umieścić
temat więc proszę o jego ewentualne przeniesienie :)
(nie umieściłem tego w projektach, bo tam to raczej gry)

Co to echo?
Hmm.. zacznijmy od tego, że jakiś czas temu wpadłem
na pomysł by napisać własną przeglądarke WWW od zera.
Już po chwili stwierdziłem, że mam na to marne szanse.
Jednakże, iż łatwo nie odpuszczam, powstało po kilku
dniach coś co nazywam echo.

echo to prosty parser xml/html parsujący proste pliki
przygotowane w tych formatach. Ładuje ono znaczniki oraz
domyślnie ich atrybuty "id" i "class", o ile występują,
w odpowiednie obiekty. Następnie dzięki kilku funkcją
oraz bazując na DOM możemy zczytywać i zmieniać te wartości.
Ponadto parser wyłapie niektóre, podstawowe błędy składniowe.

Przykładowo:
#include <iostream>
#include "document.hpp"
#include "parser.hpp"
using namespace echo::html;
int main()
{
parser::instance()->code("<a><b>A</b></a><a>BC</a>");
document *html = parser::instance()->cast();
std::cout << html->getByTag("b")[0]->getChild(0)->inner();
//wypisze "A"
return 0;
}

Kod źródłowy parsera udostępniam na zasadzie licencji BSD.
Link: http://db.tt/QU5Nvrew

Obsługę innych atrybutów niż "id" oraz "class",
atrybuty wyłącznie dla określonych znaczników itd.
należy zaprogramować samemu.

Osoby, które zechcą użyć echo w swoich projektach,
dostaną ode mnie niezbędne informacje potrzebne
do użytkowania tego parsera.

Chciałbym Was prosić o ocenę jakości itp. kodu,
wskazanie miejsc w źródle, które można byłoby ulepszyć itd.
(nie licząc całego kodu :d)

Wspomnę jeszcze tylko, że pracuję cały czas nad parserem,
także poprawki mogą pojawiać się każdego dnia.

Za błędy ortograficzne, literówki itd. bardzo przepraszam.

Pozdrawiam, Rokuzo.
« Ostatnia zmiana: Październik 24, 2012, 11:08:24 wysłana przez Rokuzo »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Paweł

  • Użytkownik

  • +1
# Październik 19, 2012, 01:55:02
Do tworzenia parserów polecam zestaw lex + bison. Bardzo fajna zabawka. Ale plus i tak leci.

Offline bies

  • Użytkownik

# Październik 19, 2012, 01:58:53
Przejrzałem tylko document.*. Kod wygląda dobrze, zmieniłbym _nodeList na vector<shared_ptr> a funkcje getByTag/Name zwracałyby vector<weak_ptr>. Mógłbyś się wtedy pozbyć destruktora.

Poza tym definicja null jest niepotrzebna. Możesz użyć NULL lub nullptr.

Offline kubera

  • Użytkownik
    • Prywatna strona

# Październik 19, 2012, 07:00:58
Witam!

Widzę tu wiele pętli for, potencjalnie może to spowodować niską wydajność.
(mówiąc językiem bazodanowców - "full-scan", chodzi o aktualne zastosowanie wektora, jako struktury przeszukiwanej).

Zamiast:
std::vector<node *> &document::getByClass(std::string className)
Czasami lepiej jest pisać:
std::vector<node *> &document::getByClass(const std::string & className)(choć nie wiem, być może kompilator to zoptymalizuje)

Czy jest sens kodować analizator XMLa?
Nie lepiej skorzystać z biblioteki, którą wykonywali inni programiści i zjedli na tem zęby?

Offline Avaj

  • Użytkownik

# Październik 19, 2012, 10:04:46
Tagi typu <a foo="bar" /> też łapie?

Offline hashedone

  • Użytkownik

# Październik 19, 2012, 11:48:47
Nie mam teraz czasu tego sprawdzać (jutro weekend to może pobiorę), ale jestem ciekaw jak sobie poradzi z parsowaniem:
Język HTML <b>dopuszcza <i>przeplatanie</b> znaczników</i>!Jest to chyba jedna z najtrudniejszych rzeczy przy parsowaniu tego języka (parsowanie XML jest wbrew pozorom bardzo proste jeśli użyje się do tego odpowiednich narzędzi, eg. wspomniane flex i bison).
« Ostatnia zmiana: Październik 19, 2012, 14:23:32 wysłana przez hashedone »

Offline kadet

  • Użytkownik

  • +1
# Październik 19, 2012, 14:38:36
Co w tym trudnego ? Jak widzi "i" to następny tag kończący ma być "i" jak nie to wypluwa błąd, nie widzę problemu. Sam ostatnio pisałem taki parser i nie było z tym żadnego problemu, najgorsze jest rozróżnianie pustych elementów imho.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

  • +1
# Październik 19, 2012, 15:20:23
Cytuj
Co w tym trudnego ? Jak widzi "i" to następny tag kończący ma być "i" jak nie to wypluwa błąd, nie widzę problemu.
No i to właśnie jest problem. Użytkownika nie obchodzi, czy znaczniki są przeplecione, podomykane, czy co tam jeszcze innego można skopać w HTML. Strona ma się wyświetlić i tyle. Bo jak w takiej sytuacji zgłosisz błąd, to użytkownik po prostu odinstaluje Twój program i odpali IE/Firefoxa.

Parsowanie HTML jest o tyle ciekawe, że obowiązuje tu zasada "best effort". Nie masz prawa zgłosić błędu i musisz wyświetlić stronę najlepiej jak potrafisz.

Offline hashedone

  • Użytkownik

  • +1
# Październik 19, 2012, 17:55:50
Co w tym trudnego ? Jak widzi "i" to następny tag kończący ma być "i" jak nie to wypluwa błąd, nie widzę problemu. Sam ostatnio pisałem taki parser i nie było z tym żadnego problemu, najgorsze jest rozróżnianie pustych elementów imho.
Zgłoszenie błędu jest w tym przypadku błędem nie tylko z powodu o jakim powiedział Krzysiek K., ale także dla tego, że z punktu widzenia języka HTML (przynajmniej w wersji 4.0 która jest chyba ciągle najpopularniejsza, z resztą raczej się to w 5.0 nie zmieniło) błędem nie jest. Błędem jest to w języku XHTML który jest pochodną XMLa i który miał z założenia wyprzeć HTML, ale coś mu się nie udało. Poza tym w HTML niektóre znaczniki w cale nie muszą mieć domknięcia - to jest dopiero problem przy parsowaniu. Nie jestem pewien co masz na myśli przez puste znaczniki, bo jeśli takie, w stylu: "<p></p>", to jest to raczej proste.

Offline Avaj

  • Użytkownik

# Październik 19, 2012, 19:47:40
Zgłoszenie błędu jest w tym przypadku błędem nie tylko z powodu o jakim powiedział Krzysiek K., ale także dla tego, że z punktu widzenia języka HTML (przynajmniej w wersji 4.0 która jest chyba ciągle najpopularniejsza, z resztą raczej się to w 5.0 nie zmieniło) błędem nie jest. Błędem jest to w języku XHTML który jest pochodną XMLa i który miał z założenia wyprzeć HTML, ale coś mu się nie udało. Poza tym w HTML niektóre znaczniki w cale nie muszą mieć domknięcia - to jest dopiero problem przy parsowaniu. Nie jestem pewien co masz na myśli przez puste znaczniki, bo jeśli takie, w stylu: "<p></p>", to jest to raczej proste.
XHTMLowi się nie udało bo przeglądarki mają całe podsystemy odpowiedzialne za to, żeby działało coś sprzed 50 lat. Jak dla mnie to powinni zrobić coś w stylu Legacy Mode Browsing, że tam możesz sobie stare strony przeglądać, ale tego już nie rozwijają, tylko dla kompatybilności zostawione, i Modern Mode Browsing, w którym działa tylko XHTML. Byłby płacz, ale po miesiącu okazałoby się, że każda sensowna strona jedzie ładnie na XHTML, a jeśli któraś się nie przerzuciła to znaczy, że i tak nie była warta uwagi.

Niestety w webdevie lubią ciągnąć kompatybilność wsteczną do końca, co widać wyraźnie po javascripcie. Mówienie, że jQuery załatwia sprawę to mydlenie oczu, bo to nie o to powinno chodzić, że biblioteka próbuje załapać wszystkie możliwe kombinacje przeglądarek.

Offline Rokuzo

  • Użytkownik
    • Masz na sprzedaż klucze do cs go?

# Październik 19, 2012, 22:13:18
Witam ponownie :)
Dzięki za jakiekolwiek komentarze co do echo. ^^

Poprawiłem po pierwsze zwracanie nulla (rzutowanie 0 na void, czyli kochane makro NULL, bo nullptr niestety
nie istnieje dla mojego g++ na androidzie..)

Zastanawiam się co do użycia weak_ptr itd. ;)

Znaczniki singleton? No problem, na dzień dzisiejszy echo zgłosi tylko brak domknięcia
bez wstrzymywania programu ;) Niestety singleton zostanie potraktowany jako rodzic
dla kolejnych znaczników ale w ciągu kilku dni zostanie ten problem usunięty..

Bo zaczynam powolutku pisać klasę, która będzie kontrolowała parsing.
Będziemy mogli zdefiniować które znaczniki muszą mieć domknięcie (brak = tylko błąd lub pominięcie, lub i to i to
lub jeszcze inne możliwości), a które nie potrzebują go koniecznie, a które są singleton.
Będziemy mogli zdefiniować np., że parser będzie próbował dla znacznika "img" zczytać
wartość atrybutu "src" (oczywiście jeżeli istnieje) itp. Takich różnych możliwości będzie wiele.

Przeplatanie? Nie próbowałem tego jeszcze ale raczej rade da co wynika z algorytmu jaki wymyśliłem.
Jakby co nie podglądam żadnych innych parserów, dokumentacji silników przeglądarek itp. itd. ^^
Kieruje się tylko swoim doświadczeniem w tworzeniu stron WWW.

To już chyba wszystko :)

Btw. widzę, że rozpoczął się ładny pod temat ;>
Co do niego, ja na to patrzę tak.
Coś nie jest napisane, jak powinno?
Zgłoś błąd webmasterowi tak by wiedział co poprawić,
ale parsuj dokument dalej nie zważając na uprzednie "usterki".

Pozdrawiam.
« Ostatnia zmiana: Październik 20, 2012, 00:08:16 wysłana przez Rokuzo »

Offline dynax

  • Użytkownik

# Październik 20, 2012, 12:02:56
Poprawiłem po pierwsze zwracanie nulla (rzutowanie 0 na void, czyli kochane makro NULL, bo nullptr niestety
nie istnieje dla mojego g++ na androidzie..)

Zasysasz NDK wersja r8 i w opcjach kompilacji wrzucasz
APP_STL := gnustl_static
APP_TOOLCHAIN_VERSION := 4.6.3
APP_USE_CPP0X := true

Masz wtedy dostęp do C++0x na Andku :)

Offline kadet

  • Użytkownik

# Październik 21, 2012, 11:50:54
Kto Wam takich bzdur naopowiadał, że html to wspiera? To, że przeglądarki to obsługują bo starają się być idiotoodporne to nie znaczy, że jest to w standardzie. Owszem, html nie jest XML'em (choćby atrybuty bez wartości typu "selected:), ale w tym wypadku są zgodne... Jeżeli nadal twierdzicie, że macie racje, zróbcie stronę z takim kwiatkiem i sprawdźcie validatorem.
« Ostatnia zmiana: Październik 21, 2012, 12:26:00 wysłana przez kadet »

Offline Rokuzo

  • Użytkownik
    • Masz na sprzedaż klucze do cs go?

# Październik 25, 2012, 22:08:28
Cześć wszystkim.

Od mojego ostatniego posta zmieniło sie kilka rzeczy w parserze.
Codziennie coś do niego dopisuje, a że są to rzeczy oczywiście warte uwagi xd, mam zamiar Was nimi pomęczyć.
1. Parser posiada teraz jakby dwa tryby:
-xml: domyślny tryb, znczniki domyślnie muszą być domykane, nie ma atrybutów singleton,
whitespaces między wyrazami są domyślnie dozwolone.
-html: znaczniki mają kilka opcji domknięcia (pracuję nad tym), atrybuty singleton (zaraz będą),
między wyrazami pozostaje tylko jedna spacja.
2. Doszedł kontroler, który właśnie pozwala zadecydować czy chcemy parsować plik xml czy html.
Pozwala też na kilka innych rzeczy ale napiszę o tym później i to już raczej szczegółowo.
3. Kod uległ lekkim, jak i większym poprawką, ogólnie modyfikacją (sposób działania kilku funkcji się zmienił itd.).
4. Powoli zaczynam się przymierzać do pisania dokumentacji parsera (nie wiem co lepiej, strona www czy dokument worda ew. pdf).
5. Dropbox został podzielony na część stable (wersja, która się poprawnie skompiluje i uruchomi) oraz work (dla bezpieczeństwa zapisuje co jakiś czas wersje, która niekoniecznie zadziała).

A i zapomniałbym o najważniejszym (żart). Parser pomija nareszcie komentarze ;)

To już chyba wszystko.
Pozdrawiam!
« Ostatnia zmiana: Październik 25, 2012, 22:33:41 wysłana przez Rokuzo »

Offline Kos

  • Użytkownik
    • kos.gd

  • +1
# Październik 25, 2012, 22:32:27
5. Dropbox został podzielony na część stable (wersja, która się poprawnie skompiluje i uruchomi) oraz work (dla bezpieczeństwa zapisuje co jakiś czas wersje, która niekoniecznie zadziała).

Praca domowa: przestać kombinować wspak i opublikować na githubie jak człowiek :).