НО - это совершенно за границы! Не повторяйте анализатор DOM / HTML, пока не разберетесь во всех фоновых технологиях

нализировать селектор CSS (CSS3) и использовать его (в стиле jQuery) для сбора элементов HTML не из DOM (из древовидной структуры), а изручей (например, SAX), т. е. использовать анализатор событий с последовательным доступом?

Кстати, есть ли CSS-селекторы (или их комбинации), которым нужен доступ к DOM (ВикипедияSAX Страница говорит, что селекторы XPath «должны иметь возможность доступа к любому узлу в любое время в разобранном дереве XML»)?

Я больше всего заинтересован в реализацииселекторные комбинаторынапример, Селектор потомка «A B».

Я предпочитаю решения, описывающие алгоритм, или в Perl (дляHTML :: Увеличить).

 VGE18 янв. 2011 г., 08:45
В каком языке вы хотите это реализовать? Вы хотите реализовать ограничение обратного вызова селектора "css"? В прошлом я разрабатывал инкрементный синтаксический анализатор XML (не SAX) для огромного xml-файла (~ 500 Мб), добавление такой функции поверх синтаксического анализатора SAX будет не таким сложным (по крайней мере, в c или C ++).
 Gerben14 янв. 2011 г., 12:42
Может быть сложно, так как SAX работают сверху вниз, в то время как CSS-селекторы оцениваются снизу вверх (справа налево). Но не невозможно.
 Jakub Narębski21 янв. 2011 г., 01:03
@VGE: Я бы предпочел Perl или описание алгоритма, но я могу читать C ++ достаточно хорошо, чтобы добраться до базового алгоритма.

Ответы на вопрос(3)

что в этом и заключается ответ на ваш вопрос, потому что он должен хранить обнаруженные элементы в форме, которая облегчает запрос селектора CSS. Если вы можете позволить себе чтение исходного кода для анализатора браузера с открытым исходным кодом, то я думаю, что вы можете использовать его повторно.

Я бы так не поступил, если честно. Скорее я бы использовал существующийSAX-анализатор (может быть тыпереписать другой с Perl), и это пройти через всю строку. Когда обработчики запускаются, используйте их для создания базы данных в памяти для элементов. Создайте виртуальную «таблицу» для каждого элемента с# номер [для ссылок] , tagName, родительский #number, следующий #number и смещение открывающего тега char в исходной материнской строке. Также создайте таблицу для каждогоатрибут когда-либо найденный, и заполните его записью для каждого тега со значением этого атрибута.

Теперь все о процессе создания базы данных, таблиц и индексов.

 Kamil Tomšík24 янв. 2011 г., 09:45
Мне нравится идея изобретать велосипед - вы можете сделать его более круглым, а если нет, то по крайней мере получите опытпочему это Как оно есть...НО - это совершенно за границы! Не повторяйте анализатор DOM / HTML, пока не разберетесь во всех фоновых технологиях
 DSimon22 янв. 2011 г., 17:13
Я скептически Разве это не просто заново изобретать колесо DOM?
 doc_id22 янв. 2011 г., 20:33
Вот почему предлагается "чтение исходного кода для парсера браузера с открытым исходным кодом"
 doc_id22 янв. 2011 г., 20:43
Тем не менее, используя прежнюю реализацию, сделанную производителями браузеров в прошлом.
 Jakub Narębski23 янв. 2011 г., 23:07
Этот ответ не очень полезен для тех, кто действительно хотел бы реализовать такую ​​вещь.

Во-первых, преобразуйте селектор в регулярное выражение, которое соответствует простому списку открытых тегов сверху вниз, представляющих данное состояние стека синтаксического анализатора. Чтобы объяснить, вот некоторые простые селекторы и соответствующие им регулярные выражения:

A становится/<A[^>]*>$/A#someid становится/<A[^>]*id="someid"[^>]*>$/A.someclass становится/<A[^>]*class="[^"]*(?<= |")someclass(?= |")[^"]*"[^>]*>$/A > B становится/<A[^>]*><B[^>]*>$/A B становится/<A[^>]*>(?:<[^>]*>)*<B[^>]*>$/

И так далее. Обратите внимание, что все регулярные выражения заканчиваются на $, но не начинаются на ^; это соответствует тому, как селекторы CSS не должны совпадать с корнем документа. Также обратите внимание на то, что в коде соответствия классов есть некоторые вещи, относящиеся к lookbehind и lookahead, что необходимо для того, чтобы вы случайно не сравнивали с «someclass-super-duper», когда вам нужен совершенно отличный класс «someclass».

Если вам нужно больше примеров, пожалуйста, дайте мне знать.

Как только вы построите регулярное выражение селектора, вы готовы начать синтаксический анализ. При разборе сохраняйте стопку тегов, которые в настоящее время применяются; обновляйте этот стек каждый раз, когда вы спускаетесь или поднимаетесь. Чтобы проверить соответствие селектора, преобразуйте этот стек в список тегов, которые могут соответствовать регулярному выражению. Например, рассмотрим этот документ:

<x><a>Stuff goes here</a><y id="boo"><z class="bar">Content here</z></y></x>

Ваша строка состояния стека будет проходить через следующие значения по порядку при вводе каждого элемента:

<x><x><a><x><y id="boo"><x><y id="boo"><z class="bar">

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

Вопросы, на которые следует обратить внимание:

Двойные кавычки внутри атрибутов. Чтобы обойти это, примените кодировку сущности html к значениям атрибутов при создании регулярного выражения и к значениям атрибутов при создании строки состояния стека.

Порядок атрибутов. При построении как регулярного выражения, так и строки состояния, используйте некоторый канонический порядок для атрибутов (алфавитный самый простой). В противном случае вы можете обнаружить, что ваше регулярное выражение для селектораa#someid.someclass что ожидает<a id="someid" class="someclass"> к сожалению, не удается, когда ваш парсер переходит в<a class="someclass" id="someid">.

Чувствительность к регистру. СогласноHTML спецификацияатрибуты class и id чувствительны к регистру (обратите внимание на маркер 'CS' на соответствующих разделах). Таким образом, вы должны использовать регистрозависимое сопоставление регулярных выражений. Однако в HTML имена элементовне чувствителен к регистру, хотя они в XML. Если вы хотите сопоставить имена элементов без учета регистра в HTML-формате, канонизируйте имена элементов либо в верхнем, либо в нижнем регистре как в регулярном выражении селектора, так и в строке стека состояний.

Дополнительная магия необходима, чтобы иметь дело с шаблонами селектора, которые включают в себя наличие или отсутствие элементов родного элемента, а именноA:first-child а такжеA + B, Вы можете сделать это, добавив специальный атрибут к тегу, содержащий имя тега непосредственно перед, или "", если этот тег является первым дочерним элементом. Там также общий выбор сестер,A ~ B; Я не совсем уверен, как справиться с этим.

РЕДАКТИРОВАТЬ: Если вам не нравится взлом регулярных выражений, вы все равно можете использовать этот подход для решения проблемы, используя толькотвой собственный конечный автомат вместо движка регулярных выражений. В частности, CSS-селектор может быть реализован какнедетерминированный конечный автомат, который является пугающим звучащим термином, но на практике означает следующее:

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

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

 DSimon29 июл. 2011 г., 04:10
Оглядываясь назад, я замечаю ошибку, которую совершил; примеры регулярных выражений селектора, которые я написал, будут сопоставляться с тегами, которые просто начинаются с нужного имени тега, поэтому селектор для «A» будет некорректно сопоставляться с тегом «Alakazam». Чтобы избежать этого, вам нужно настроить части [^>] * так, чтобы они были более похожими (?: | [^>] *), Чтобы он не начинал игнорировать неважные атрибуты до тех пор, пока пробел не укажет имя тега. закончен.

nokogiri, Со своей страницы:

Nokogiri - это анализатор HTML, XML, SAX и Reader. Среди многих функций Nokogiri - возможность поиска документов с помощью селекторов XPath или CSS3. "

Это в Ruby, но вы сказали, что хотели алгоритм, и Ruby отлично подходит для чтения. Или просто позвоните из того места, где вы работаете.

Ваш ответ на вопрос