Jump to content
  • 0

установление соответствия между тегами и CSS-селекторами


freeneutron
 Share

Question

Решаю задачу установления соответствия произвольного CSS-селектора произвольному тегу некоторого HTML-кода. То-есть, если для некоторого HTML-кода составлен такой список,

<html>
<html><head>
<html><head><title>
<html><body><div id='main'>
<html><body><div id='main'><div id='header'>
<html><body><div id='main'><div id='content'>
<html><body><div id='main'><div id='footer'>

что каждому тегу данного HTML-кода в этом списке соответствует строка, состоящая из самого тега и всех его родительских тегов, и если есть некоторый CSS-селектор, например: "#content", то моей задачей является составление (или отискание) функции is_match($string, $css) такой, которая для каждой сроки из упомянутого списка и произвольного CSS-селектора устанавливала бы их соответствие и возвращала бы true в случае соответствия и false в противном случае. Например:

is_match('<html><body><div id='main'><div id='content'>', '#content') возвращает true

is_match('<html><body><div id='main'><div id='header'>', '#content') возвращает false

Кто сталкивался с чем-то подобным, или есть какие-то соображения по поводу решения задачи, пишите. Очень хотелось бы все это обсудить.

Link to comment
Share on other sites

5 answers to this question

Recommended Posts

  • 0

Чето я с трудом осилил сие... Вам надо построчный поиск в файле? ну так и воспользуйтесь substr_count делаете цикл

$file = file("file.txt");
$str = "text";
$countfile = count($file);
for ($i = 0; $i < $countfile; $i++ ) {
$chet = substr_count($file[$i],$str);
if ( $chet > 0) { echo $file[$i]; }
}

Link to comment
Share on other sites

  • 0

Ему нужен не просто поиск, ему нужно узнать, подходит ли, допустим "div.bb span.a b.ad span", хотя бы под одну строку из списка. И то же самое для просто div.ggg.

Я правильно понял?

Link to comment
Share on other sites

  • 0

Ну тогда надо работать над логикой... запись типа "div.bb" означает что надо начинать поиск с "<div " далее с "<div " до первой ">" искать class=" где с class=" до первой " искать " bb " это все рекурсивными выражениями осуществляется не сложно, + циклы...

далее надо рассмотреть момент с поиском "div span" ищется "<div " далее ищется "<div " or "<span " or "</div" ....

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

Edited by stars
Link to comment
Share on other sites

  • 0

Вот простейший пример, который ищет наличие тегов, классов и айдишников. Само собой, надо дописать еще проверку на то, что подстрока id="content" находится внутри тега, реализовать всякие div.content и прочие селекторы, но направление, я думаю, задал

function is_match($str, $selector)
{
switch (substr($selector, 0, 1))
{
case '#':
return preg_match("~id=(\'|\")[^\'\"]*".substr($selector, 1)."[^\'\"]*(\'|\")~", $str);
break;
case '.':
return preg_match("~class=(\'|\")[^\'\"]*".substr($selector, 1)."[^\'\"]*(\'|\")~", $str);
break;
default:
return preg_match("~<".$selector."(\s|>)+~", $str);
}
}

Link to comment
Share on other sites

  • 0

Спасибо всем, кто отозвался. Да, без регулярных выражений здесь не обойтись. Но тогда почему бы не использовать их на всю катушку? У меня есть подозрение, что любой CSS-селектор можно конвертировать в соответствующее регулярное выражение, которое бы и справлялось с моей задачей. Тогда искомая функция упростится до безобразия:

function is_match($str,$selector){
$selector=css2preg($selector);
return preg_match($str,$selector);
}

А вся логика перейдет функцию конвертирования CSS-селектора в регулярное выражение:

function css2preg($selector){
//Поиск имен тегов (div, span) и приведение их к виду: (<div, <span)
$selector=preg_replace('/(^| )([^.# ]+)/','$1<$2[^<]+',$selector);
//Поиск имен классов и приведение их к виду: class=""
$selector=preg_replace('/\.(\S+)/','class="[^"]*$1[^"]*"',$selector);
//Поиск имен идентификаторов и приведение их к виду: id=""
$selector=preg_replace('/\#(\S+)/','id="[^"]*$1[^"]*"',$selector);
//Поиск пробелов и замена их на символы произвольного расстояния: .*
$selector=preg_replace('/ /','.*',$selector);
//Поиск символов > и замена их на соответствующее выражение
$selector=preg_replace('/>/','[^>]*>[^>]*',$selector);
//echo"$selector\n";
return $selector;
}

Если имеем CSS-селектор:

div.bb span.a b.ad span

То на выходе будем иметь:

<div[^<]+class="[^"]*bb[^"]*".*<span[^<]+class="[^"]*a[^"]*".*<b[^<]+class="[^"]*ad[^"]*".*<span[^<]+

Как видно для каждой синтаксической конструкции можно подобрать соответствующее правило преобразования. Здесь остается подобрать правила:

для замены символа *

для выражений в квадратных скобках

и (если я ни чего не забыл) для сброса псевдоклассов (:active и тп)

Если все это учесть, то останется еще две проблемы:

1. css2preg() не сможет правильно обрабатывать последовательности типа: .class1.class2#id1#id2

2. Как на полученные регулярные выражения будет реагировать preg_replace() не известно, то есть надо еще тестировать и подгонять.

На все это нужно время и усилия, поэтому опять же хотелось бы найти что-то готовое, и надеется на то, что оно где-то есть. Набирая в поисковике запрос: css to preg, не получаю ни чего вразумительного. Возможно, то, что мне нужно скрывается под каким-то хитрым запросом, только ни чего больше не приходит пока на ум. Поэтому, если у кого будут какие соображения, пишите, буду рад...

Edited by freeneutron
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy