Разбейте CSS-файл на массив с помощью PHP - PullRequest
7 голосов
/ 01 августа 2009

Я хотел разбить 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"
    }
  }
}

Есть идеи?

Oh: Edit: я не беспокоюсь о плохо сформированных файлах CSS в этом случае. Не может быть пуленепробиваемым, если не жадный

Ответы [ 4 ]

11 голосов
/ 01 августа 2009

Это должно сделать это:

<?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, нет никаких причин, по которым вам нужно делать что-то, кроме простейшего из "что-либо {что-нибудь}" , Зависит от того, что вы хотите с ним делать, действительно.

6 голосов
/ 01 августа 2009

Если вам нужно то же самое для правил 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\,\.\:#_\-@]+)\{([^\}]*)\}/', $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 {...}

3 голосов
/ 01 августа 2009

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

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

0 голосов
/ 14 декабря 2016

Я бы предложил выбрать (?ims)([a-z0-9\s\,\.\:#_\-@*()\[\]"=]+)\{([^\}]*)\} в ответе inakiabt для лучшего решения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...