2009-07-31 5 views
6

Я хотел разбить файл css в массив с PHP.Перерыв CSS-файла в массив с PHP

Ex:

#selector{ display:block; width:100px; } 
#selector a{ float:left; text-decoration:none; } 

в массив PHP ...

array(2) { 
    ["#selector"] => array(2) { 
    [0] => array(1) { 
     ["display"] => string(5) "block" 
    } 
    [1] => array(1) { 
     ["width"] => string(5) "100px" 
    } 
    } 
    ["#selector a"] => array(2) { 
    [0] => array(1) { 
     ["float"] => string(4) "left" 
    } 
    [1] => array(1) { 
     ["text-decoration"] => string(4) "none" 
    } 
    } 
} 

Любые идеи?

О: Редактировать: Я не беспокоюсь о плохо сформированных CSS-файлах в этом случае. Не должен быть пуленепробиваемым, пока его не жадны.

+0

К сожалению, я написал что-то, что делало это наоборот. –

ответ

11

Это следует сделать это:

<?php 

$css = <<<CSS 
#selector { display:block; width:100px; } 
#selector a { float:left; text-decoration:none } 
CSS; 

// 
function BreakCSS($css) 
{ 

    $results = array(); 

    preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $css, $matches); 
    foreach($matches[0] AS $i=>$original) 
     foreach(explode(';', $matches[2][$i]) AS $attr) 
      if (strlen(trim($attr)) > 0) // for missing semicolon on last element, which is legal 
      { 
       list($name, $value) = explode(':', $attr); 
       $results[$matches[1][$i]][trim($name)] = trim($value); 
      } 
    return $results; 
} 
var_dump(BreakCSS($css)); 

Быстрый Объяснение: Регулярное выражение просто и скучный. Он просто соответствует всем «всем, возможному пространству, фигурной скобке, возможному пространству, чему угодно, закрывает фигурные скобки». Оттуда первое совпадение является селектором, второе совпадение - списком атрибутов. Разделите это точкой с запятой, и вы останетесь с парами ключ/значение. Некоторые trim() там, чтобы избавиться от пробелов, и это все.

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

Редактировать: Как уже упоминалось выше, реальный грамматический анализатор был бы более практичным ... но если вы принимаете хорошо сформированный CSS, нет причин, по которым вам нужно делать что-либо помимо простейшего из " что-нибудь }". На самом деле зависит от того, что вы хотите с этим делать.

+0

..'sexplode() 'eh? Я сделал двойной прием и проверил руководство: P – Dan

+0

Я перевел это на Python во время процесса миграции в одном из моих проектов, если вам интересно, [проверьте это] (https: //gist.github .com/pooh110andco/5177066). – Ale

+1

Не работает по указанным правилам :-( – sumid

2

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

Пример: http://www.phpclasses.org/package/1289-PHP-CSS-parser-class.html

7

Если вам нужно то же самое для правил CSS с несколькими селекторов и структурных линий:

<?php      
$css = " 
#selector 
{ display:block; 
width:100px; 
} 
#selector a:hover div.asd, #asd h1.asd { 
float:left; 
text-decoration:none; 
} 
"; 
preg_match_all('/(?ims)([a-z0-9\s\,\.\:#_\[email protected]]+)\{([^\}]*)\}/', $css, $arr); 

$result = array(); 
foreach ($arr[0] as $i => $x) 
{ 
    $selector = trim($arr[1][$i]); 
    $rules = explode(';', trim($arr[2][$i])); 
    $result[$selector] = array(); 
    foreach ($rules as $strRule) 
    { 
     if (!empty($strRule)) 
     { 
      $rule = explode(":", $strRule); 
      $result[$selector][][trim($rule[0])] = trim($rule[1]); 
     } 
    } 
} 

var_dump($result); 
?> 

выход:

array(2) { 
    ["#selector"]=> 
    array(2) { 
    [0]=> 
    array(1) { 
     ["display"]=> 
     string(5) "block" 
    } 
    [1]=> 
    array(1) { 
     ["width"]=> 
     string(5) "100px" 
    } 
    } 
    ["#selector a:hover div.asd, #asd h1.asd"]=> 
    array(2) { 
    [0]=> 
    array(1) { 
     ["float"]=> 
     string(4) "left" 
    } 
    [1]=> 
    array(1) { 
     ["text-decoration"]=> 
     string(4) "none" 
    } 
    } 
} 

Обновление: Добавлена ​​поддержка нескольких селекторов, как: .box, .element , div {...}

+0

Не работает правильно, если селектор несколько: .box, .element, div {...} – setty

+0

Обновлено. Спасибо. – inakiabt

+1

Хорошо, но не работает с 'background-image: url ("data: image/png; base64, ........' тип значений .. –