HTML / XML jest podzielony na znaczniki i treść. Regex jest użyteczny tylko podczas analizy tagów leksykalnych. Myślę, że możesz wydedukować treść. Byłby to dobry wybór dla parsera SAX. Tagi i treść mogą być dostarczane do funkcji zdefiniowanej przez użytkownika, w której można śledzić zagnieżdżanie / zamykanie elementów.
Jeśli chodzi o samą analizę tagów, można to zrobić za pomocą wyrażenia regularnego i użyć do usunięcia tagów z dokumentu.
Przez lata testów odkryłem sekret sposobu, w jaki przeglądarki analizują tagi, zarówno dobrze, jak i źle sformułowane.
Normalne elementy są przetwarzane w tej formie:
Rdzeń tych tagów używa tego wyrażenia regularnego
(?:
" [\S\s]*? "
| ' [\S\s]*? '
| [^>]?
)+
Zauważysz to [^>]?
jako jedną z alternatyw. To dopasuje niezrównoważone cytaty z źle sformułowanych tagów.
Jest także jednym z głównych źródeł wszelkiego zła źródeł wyrażeń regularnych. Sposób, w jaki jest używany, spowoduje wyboistość, aby zaspokoić jego zachłanny, dopasowany ilościowo pojemnik.
Jeśli użyjesz go biernie, nigdy nie będzie problemu. Ale jeśli wymusisz coś dopasować przez przeplatając je z kupna parę atrybut / wartość, i nie zapewniają odpowiedniej ochrony przed backtracking, to jest poza kontrolą koszmar.
Jest to ogólna forma zwykłych starych tagów. Zauważ, że [\w:]
reprezentuje nazwę znacznika? W rzeczywistości znaki prawne reprezentujące nazwę znacznika to niesamowita lista znaków Unicode.
<
(?:
[\w:]+
\s+
(?:
" [\S\s]*? "
| ' [\S\s]*? '
| [^>]?
)+
\s* /?
)
>
Przechodząc dalej, widzimy również, że po prostu nie możesz wyszukać określonego tagu bez analizy WSZYSTKICH tagów. Mam na myśli, że możesz, ale musiałbyś użyć kombinacji czasowników takich jak (* SKIP) (* FAIL), ale nadal wszystkie tagi muszą zostać przeanalizowane.
Powodem jest to, że składnia znaczników może być ukryta w innych znacznikach itp.
Aby pasywnie przeanalizować wszystkie tagi, potrzebny jest regex, taki jak poniżej. Ten konkretny pasuje również do niewidzialnej treści .
Gdy nowy HTML lub xml lub jakikolwiek inny opracuje nowe konstrukcje, po prostu dodaj go jako jedną z alternatyw.
Informacja o stronie internetowej - Nigdy nie widziałem strony internetowej (lub xhtml / xml), z którą
miałby to problem. Jeśli znajdziesz, daj mi znać.
Uwaga dotycząca wydajności - jest szybka. To najszybszy parser tagów, jaki widziałem
(może być szybszy, kto wie).
Mam kilka konkretnych wersji. Jest również doskonały jako skrobak
(jeśli jesteś typem praktycznym).
Wypełnij wyrażenie regularne
<(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\1\s*(?=>))|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]?)+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>
Sformatowany wygląd
<
(?:
(?:
(?:
# Invisible content; end tag req'd
( # (1 start)
script
| style
| object
| embed
| applet
| noframes
| noscript
| noembed
) # (1 end)
(?:
\s+
(?>
" [\S\s]*? "
| ' [\S\s]*? '
| (?:
(?! /> )
[^>]
)?
)+
)?
\s* >
)
[\S\s]*? </ \1 \s*
(?= > )
)
| (?: /? [\w:]+ \s* /? )
| (?:
[\w:]+
\s+
(?:
" [\S\s]*? "
| ' [\S\s]*? '
| [^>]?
)+
\s* /?
)
| \? [\S\s]*? \?
| (?:
!
(?:
(?: DOCTYPE [\S\s]*? )
| (?: \[CDATA\[ [\S\s]*? \]\] )
| (?: -- [\S\s]*? -- )
| (?: ATTLIST [\S\s]*? )
| (?: ENTITY [\S\s]*? )
| (?: ELEMENT [\S\s]*? )
)
)
)
>