preg_match атрибуты тегов

Тема в разделе "PHP", создана пользователем venetu, 13 окт 2011.

Модераторы: latteo
  1. venetu

    venetu

    Регистр.:
    28 мар 2007
    Сообщения:
    735
    Симпатии:
    261
    Вопрос мой скорее для раздела RegExps, но учитывая общий уровень нынешнего Нуледа, здесь единственный шанс, что кто-то ответит по теме. Потом можно будет перенести тред туда (если ответят!). Итак,

    Мне нужно выцепить все style= из html. Не <style>..</style>, а именно значения атрибута style у всех тегов. Т.е. поймать всякие

    <a style=border:0>
    <table style= "padding:0; background:url('img.jpg') 0 0 no-repeat">
    <div style=' font-face:"Times New Roman" '>
    <div style =
    "font-face:\"Times New Roman\"">
    и т.д.

    Строим регексп:

    \s+ перед style обязательно стоит минимум один пробельный символ
    style собственно слово "style"
    \s*=\s* "равно", возможно разделенное пробельными символами

    теперь дальше начинается шаманство:

    ["']? если начинается с кавычки, то мы должны дойти до конца пока не встретим такую же кавычку

    если же открывающей кавычки не было - мы идем пока не найдем пробел, таб или закрывающий тег символ >

    Дальше у нас собственно паттерн поиска, который зависит от предыдущего шага (Conditional subpattern). Т.е. мы ищем или
    (1) такую же кавычку, или
    (2) пробел или >

    "Такая же" кавычка записывается как \1 - Back-reference на первую. Т.е. если начиналось на одинарную, то дальше мы ищем только одинарные, если начиналось с двойной - будем искать двойные. Здесь есть нюанс, что перед кавычкой не должно быть \ или их должно быть четное количество. Это можно записать как

    [^\\](\\\\)*\1 т.е. не бекслеш, потом 0 или более пар бекслешей и \1 - "референс на предыдущую кавычку".

    Если же паттерн не начинался с кавычек, то тут все просто

    [^>\s]+ - не закрытие тега и не таб, пробел, перевод строки и другой пробельный символ.


    Ну и в общем теперь, собственно, вопрос: помогите это все собрать в кучу.


    PS: Пожалуйста не предлагайте DOMDocument, PHPQuery и пр. Я про них знаю, с ними данная задача решается элементарно.
     
  2. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    883
    Симпатии:
    540
    мне кажется что нужно объять необъятное) если ещё теоритически можно встретит без кавычек, то при использовании слешей - получится невалидный html который скорее всего и работать не будет нигде.
    Хотя вот что то накропал на ночь глядя-
    PHP:
    ob_start( );
    ?>
    <style>
    not
    </style> 
     <a href="htp://1" style=border:1 class=""></a> 
     <a href="http://1" style="border:1" class=""></a>
     <a href="http://1" style = 'border:"2"'  class=""></a> 
     <a href="http://1" style = "border:\"3\" sss "  class=""></a>  
     <a href="http://1" style = "border:\\\"4\\\""  class=""></a>   
    <?php
    $e 
    ob_get_contents();
    ob_end_clean();
    preg_match_all('~\sstyle\s*=\s*([\'"])?
        (?(1)  
            ([^\\\]+?
                (
               (\\\ \1)
                   |
               (\\\(\\\\\\\)* \1)
                )?
             )*?
            ((\\\\\\\)*)?
          \1 
          |
          (.*?)\s
        )~isx'
    $e$html );
    print_r($html);
    посмотри, возможно какой нибуть случай не учёл. + есть предположение что дум парсеры не используются из-за скорости, я не уверен что это выражение будет очень быстрым- есть вариант найти все строки style=[^>]*?> и посимвольно разобрать из в пхп.
     
    venetu нравится это.