Czy możesz podać kilka przykładów, dlaczego trudno jest analizować XML i HTML za pomocą wyrażenia regularnego? [zamknięte]

Jeden błąd widzę ludzi robi nad i ponownie próbuje parsować XML lub HTML z regex. Oto kilka powodów, dla których parsowanie XML i HTML jest trudne:

Ludzie chcą traktować plik jako ciąg wierszy, ale jest to poprawne:

<tag
attr="5"
/>

Ludzie chcą traktować znacznik

<img src="imgtag.gif" alt="<img>" />

Ludzie często chcą dopasować znaczniki początkowe do znaczników końcowych, ale XML i HTML pozwalają znaczniki zawierać same (których tradycyjne wyrażenia regularne w ogóle nie mogą obsłużyć):

<span id="outer"><span id="inner">foo</span></span> 

Ludzie często chcą dopasować treść dokumentu (np. słynny problem "znajdź wszystkie numery telefonów na danej stronie"), ale dane mogą być oznaczone (nawet jeśli wydaje się, że są normalne po wyświetleniu): {]}

<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>

Komentarze mogą zawierać źle sformatowane lub niekompletne tagi:

<a href="foo">foo</a>
<!-- FIXME:
    <a href="
-->
<a href="bar">bar</a>
O jakich jeszcze gotchach wiesz?
 377
Author: Community, 2009-03-31

12 answers

Oto zabawa valid XML dla Ciebie:

<!DOCTYPE x [ <!ENTITY y "a]>b"> ]>
<x>
    <a b="&y;>" />
    <![CDATA[[a>b <a>b <a]]>
    <?x <a> <!-- <b> ?> c --> d
</x>

I ta mała paczka radości jest poprawna:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" [
    <!ENTITY % e "href='hello'">
    <!ENTITY e "<a %e;>">
]>
    <title>x</TITLE>
</head>
    <p id  =  a:b center>
    <span / hello </span>
    &amp<br left>
    <!---- >t<!---> < -->
    &e link </a>
</body>

Nie wspominając o wszystkich analizach dla błędnych konstrukcji specyficznych dla przeglądarki.

Powodzenia w pisaniu regex przeciwko temu!

EDIT (Jörg W Mittag): oto kolejny ładny kawałek dobrze uformowanego, poprawnego HTML 4.01:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd"> 
<HTML/
  <HEAD/
    <TITLE/>/
    <P/>
 247
Author: bobince,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 22:02:56

Właściwie

<img src="imgtag.gif" alt="<img>" />

Nie jest poprawnym HTML i nie jest poprawnym XML.

To nie jest poprawny XML, ponieważ ' ' nie są poprawnymi znakami wewnątrz ciągów atrybutów. Muszą być zabezpieczone za pomocą odpowiednich encji XML

Nie jest poprawny HTML, ponieważ krótka forma zamykająca nie jest dozwolona w HTML (ale jest poprawna w XML i XHTML). Znacznik ' img ' jest również domyślnie zamkniętym znacznikiem zgodnie ze specyfikacją HTML 4.01. Oznacza to, że ręcznie zamknięcie go jest w rzeczywistości złe i jest równoznaczne z dwukrotnym zamknięciem każdego innego tagu.

Poprawna wersja w HTML to

<img src="imgtag.gif" alt="&lt;img&gt;">

A poprawną wersją w XHTML i XML jest

<img src="imgtag.gif" alt="&lt;img&gt;"/>

Poniższy przykład, który podałeś, jest również nieprawidłowy

<
tag
attr="5"
/>

To również nie jest poprawny HTML ani XML. Nazwa tagu musi znajdować się tuż za' ' mogą znajdować się tam, gdzie chcą. Tak więc poprawny XML to w rzeczywistości

<tag
attr="5"
/>

A oto kolejny bardziej funkcyjny: możesz użyć " lub " jako atrybutu cytującego znak

<img src="image.gif" alt='This is single quoted AND valid!'>

Wszystkie inne powody, które zostały opublikowane są poprawne, ale największym problemem przy analizowaniu HTML jest to, że ludzie zwykle nie rozumieją wszystkich zasad składni poprawnie. Fakt, że twoja przeglądarka interpretuje tagsoup jako HTML nie oznacza, że rzeczywiście napisałeś poprawny HTML.

Edit: a nawet stackoverflow.com zgadza się ze mną co do definicji ważnych i nieważne. Twój nieprawidłowy XML / HTML nie jest podświetlony, podczas gdy moja poprawiona wersja jest.

Zasadniczo XML nie jest przeznaczony do parsowania z wyrażeniami regularnymi. Ale nie ma też ku temu powodu. Istnieje wiele parserów XML dla każdego języka. Masz wybór pomiędzy PARSERAMI SAX, PARSERAMI DOM i Parserami Pull. Wszystkie z nich są gwarantowane, że będą znacznie szybsze niż parsowanie z wyrażeniem regularnym, a następnie możesz użyć fajnych technologii, takich jak XPath lub XSLT na wynikowym drzewie DOM.

Moja odpowiedź to dlatego: nie tylko parsowanie XML z wyrażeniami regularnymi jest trudne, ale jest to również zły pomysł. Wystarczy użyć jednego z milionów istniejących parserów XML i skorzystać ze wszystkich zaawansowanych funkcji XML.

HTML jest po prostu zbyt trudny do samodzielnego parsowania. Po pierwsze składnia prawna ma wiele małych subtelności, których możesz nie być świadomy, a po drugie, HTML in the wild to po prostu ogromny śmierdzący stos (rozumiesz o co mi chodzi). Istnieje wiele bibliotek parserów lax, które dobrze radzą sobie z obsługą HTML jak zupa z tagiem, użyj tego.

 64
Author: LordOfThePigs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 15:06:25

Napisałem cały wpis na blogu na ten temat: ograniczenia wyrażeń regularnych

Sednem problemu jest to, że HTML i XML są strukturami rekurencyjnymi, które wymagają mechanizmów liczenia w celu poprawnego parsowania. Prawdziwy regex nie jest w stanie zliczyć. Musisz mieć gramatykę bez kontekstu, aby liczyć.

Poprzedni akapit ma niewielkie zastrzeżenie. Niektóre implementacje regex wspierają obecnie ideę rekurencji. Jednak po rozpoczęciu dodawania rekurencja do wyrażeń regex, naprawdę rozciągasz granice i powinieneś rozważyć parser.

 52
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-08 02:00:45

Nie ma na twojej liście tego, że atrybuty mogą pojawić się w dowolnej kolejności, więc jeśli Twoje regex szuka łącza z href " foo "i klasą "bar", mogą pojawić się w dowolnej kolejności i mieć dowolną liczbę innych rzeczy między nimi.

 19
Author: AmbroseChapel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-01 05:58:55

To zależy co masz na myśli przez "parsowanie". Ogólnie rzecz biorąc, XML nie może być parsowany za pomocą regex, ponieważ gramatyka XML nie jest w żaden sposób regularna. Mówiąc prościej, wyrażenia regularne nie mogą liczyć (cóż, wyrażenia regularne Perla mogą faktycznie być w stanie liczyć rzeczy), więc nie można zrównoważyć znaczników open-close.

 15
Author: Anton Gogolev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 14:16:30

Czy ludzie rzeczywiście popełniają błąd używając wyrażenia regularnego, czy jest to po prostu wystarczająco dobre dla zadania, które próbują osiągnąć?

Całkowicie się Zgadzam, że parsowanie html i xml za pomocą wyrażenia regularnego nie jest możliwe, jak odpowiedziały inne osoby.

Jednakże, jeśli twoim wymogiem nie jest analizowanie html / xml, ale uzyskanie jednego małego bitu danych w" znanym dobrym " bitie html / xml, może wystarczy Wyrażenie regularne lub nawet jeszcze prostszy "podłańcuch".

 9
Author: Robin Day,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 14:29:24

Ludzie zwykle domyślają się pisania zachłannych wzorców, co często prowadzi do nieprzemyślania .* wsuwanie dużych fragmentów pliku do największego możliwego .*.

 6
Author: chaos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 14:20:06

Kusi mnie, żeby powiedzieć "nie wymyślaj koła na nowo". Poza tym, że XML jest naprawdę, Naprawdę złożonym formatem. Więc może powinienem powiedzieć " nie odkrywaj synchrotronu na nowo."

Być może poprawny frazes zaczyna się "kiedy wszystko, co masz, to młotek..."Wiesz, jak używać wyrażeń regularnych, wyrażenia regularne są dobre w parsowaniu, więc dlaczego warto uczyć się biblioteki parsowania XML?

Ponieważ parsowanie XML jest trudne . Każdy wysiłek, który oszczędzasz, nie musisz uczyć się korzystać z parsowania XML biblioteka będzie więcej niż nadrobiona przez ilość pracy twórczej i usuwania błędów, które będziesz musiał zrobić. Dla własnego dobra, google "biblioteka XML" i wykorzystać czyjąś pracę.

 6
Author: Isaac Rabinovitch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-14 23:52:04

I believe this classic zawiera informacje, których szukasz. Możesz znaleźć punkt w jednym z komentarzy tam:

Myślę, że wadą jest to, że HTML to gramatyka typu Chomsky 2 (gramatyka bezkontekstowa) i RegEx to gramatyka typu Chomsky 3 (regularna wyrażenie). ponieważ gramatyka typu 2 jest zasadniczo bardziej złożona niż A Type 3 grammar - you can ' t likely hope to make this work . Ale wiele spróbuje, niektórzy będą twierdzić sukces i inni znajdą winę i totalnie Cię namieszało.

Trochę więcej informacji z Wikipedii: hierarchia Chomsky ' ego

 4
Author: Adam Arold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:47

Myślę, że problemy sprowadzają się do:

  1. Regex jest prawie niezmiennie niepoprawny. Istnieją legalne dane wejściowe, które nie będą poprawnie dopasowane. Jeśli pracujesz wystarczająco ciężko, możesz sprawić, że będzie to 99% poprawne lub 99,999%, ale poprawienie tego w 100% jest prawie niemożliwe, choćby z powodu dziwnych rzeczy, na które XML pozwala używając encji.

  2. Jeśli regex jest niepoprawny, nawet dla 0.00001% wejść, to masz problem z bezpieczeństwem, ponieważ ktoś może odkryć jedyne wejście, które złamie Twoją aplikację.

  3. Jeśli regex jest wystarczająco poprawny, aby pokryć 99.99% przypadków, to będzie całkowicie nieczytelne i nie do utrzymania.

  4. Jest bardzo prawdopodobne, że wyrażenia regularne będą działać bardzo źle na średniej wielkości plikach wejściowych. Moim pierwszym spotkaniem z XML było zastąpienie skryptu Perla, który (nieprawidłowo) parsował przychodzące dokumenty XML odpowiednim parserem XML, a nie tylko zastąpiliśmy 300 wierszy nieczytelnego kodu 100 linie, które każdy mógł zrozumieć, ale poprawiliśmy czas reakcji użytkownika z 10 sekund do około 0,1 sekundy.

 4
Author: Michael Kay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-22 10:26:10

Ogólnie rzecz biorąc, XML nie może być parsowany za pomocą regex, ponieważ gramatyka XML nie jest w żaden sposób regularna. Mówiąc prościej, wyrażenia regularne nie mogą liczyć (cóż, wyrażenia regularne Perla mogą faktycznie być w stanie liczyć rzeczy), więc nie można zrównoważyć znaczników open-close.

Nie zgadzam się. Jeśli użyjesz rekurencyjnego w regex, możesz łatwo znaleźć otwarte i zamknięte znaczniki.

Tutaj pokazałem przykład regex, aby uniknąć błędów parsowania przykładów w pierwszej wiadomości.

 1
Author: Maxim Suslov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:39

Udzieliłem uproszczonej odpowiedzi na ten problem tutaj . Chociaż nie odpowiada to 100% marży, wyjaśniam, jak to możliwe, jeśli jesteś gotów wykonać pewne wstępne przetwarzanie.

 1
Author: Erutan409,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:49