【问题标题】:Parse a CSS file with PHP使用 PHP 解析 CSS 文件
【发布时间】:2011-04-06 19:29:11
【问题描述】:

我想用 PHP 解析(以特殊方式)一个 CSS 文件。

例子:

cssfile.css:

#stuff {
    background-color: red;
}

#content.postclass-subcontent {
    background-color: red;
}

#content2.postclass-subcontent2 {
    background-color: red;
}

而且我希望 PHP 向我返回名称中包含 postclass 的每个类名。

在这个例子中,结果看起来像一个数组:

arrayentry1:
#content.postclass-subcontent
arrayentry2:
#content2.postclass-subcontent2

但我更擅长正则表达式。以某种方式搜索“postclass”,然后抓住孔线并放入一个数组中。


谢谢你,我用它来解析一个类似于 confic 文件的 css 文件。

$(function () {
    $.get('main.css', function (data) {
        data = data.match(/(#[a-z0-9]*?\ .?postclass.*?)\s?\{/g);
        if (data) {
            $.each(data, function (index, value) {
                value = value.substring(0, value.length - 2);
                $(value.split(' .')[0]).wrapInner('<div class="' + value.split('.')[1] + '" />');
            });
        }
    });
});

是我的最终代码。所以我可以在不编辑布局的情况下轻松地将 div 包裹在一些 hardcode-html 周围。所以我只需要编辑我的 cssfile 并添加类似的东西

id .postclass-class { 一些样式 }

我的代码搜索 id 并用 div 包装内部内容。当我只需要在某物周围添加一个 div 以获得清晰或背景时,我需要它来进行快速修复。

【问题讨论】:

  • 你有没有试过的代码,如果有的话,发布一下会有帮助。
  • Parsing CSS by regex 的可能重复项

标签: php css regex parsing


【解决方案1】:

PHP 中有一个很好的CSS parser class。用它。这是它的示例代码:

<?php
include("cssparser.php");

$css = new cssparser();
$css->ParseStr("b {font-weight: bold; color: #777777;} b.test{text-decoration: underline;}");
echo $css->Get("b","color");     // returns #777777
echo $css->Get("b.test","color");// returns #777777
echo $css->Get(".test","color"); // returns an empty string
?> 

【讨论】:

  • 谢谢。但不需要价值和开销!还是谢谢你
  • 该课程可追溯到 2003 年 9 月 20 日。 (而且该网站还要求您进行烦人的注册才能下载它。)
【解决方案2】:

我找到了解决办法:

function parse($file){
    $css = file_get_contents($file);
    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]));
        $rules_arr = array();
        foreach ($rules as $strRule){
            if (!empty($strRule)){
                $rule = explode(":", $strRule);
                $rules_arr[trim($rule[0])] = trim($rule[1]);
            }
        }
        
        $selectors = explode(',', trim($selector));
        foreach ($selectors as $strSel){
            $result[$strSel] = $rules_arr;
        }
    }
    return $result;
}

使用:

$css = parse('css/'.$user['blog'].'.php');
$css['#selector']['color'];

【讨论】:

  • 太棒了。它开箱即用。但它不能正确读取base64 格式的url()。喜欢:[#logo] =&gt; Array ( [background-image] =&gt; url("data [base64,....................] =&gt; [background-size] =&gt; auto 100% )
  • 不错,但也有一些问题 - 1) 它不能处理子选择器(>) 2) 它不能处理像 input[type="button"]:hover 这样的选择器。
  • 正则表达式不匹配所有可能的选择器,如果有人正在寻找更精细的 /([a-z0-9\s\.\:#_\-@,%\[\]()'"=*\\&gt;~\/+]+)\{([^\}]*)\}/gsi 匹配我所有的选择器
【解决方案3】:

为了完整起见,还有另一个用于解析 CSS 的库:sabberworm / PHP-CSS-Parser

主页:http://www.sabberworm.com/blog/2010/6/10/php-css-parser
GitHub:http://github.com/sabberworm/PHP-CSS-Parser
要点:http://packagist.org/packages/sabberworm/php-css-parser
最后更新:2017 年 5 月 31 日(之所以这样说是因为博客条目中的日期可能会误导您认为它不再更新。)

不幸的是,这个项目有点太健壮了。从非常简单的 CSS 创建非常健谈的结构。同样在第一次使用之前,你必须处理作曲家(我自己最终将每个文件的 require_once 添加到 parser.php 中)。

【讨论】:

  • 这个解决方案只有一个小问题,它不支持媒体查询。
  • 它现在确实提供媒体查询。
【解决方案4】:
<?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($attr) > 0) // for missing semicolon on last element, which is legal
                {
                        // Explode on the CSS attributes defined
                        list($name, $value) = explode(':', $attr);
                        $results[$matches[1][$i]][trim($name)] = trim($value);
                }
    return $results;
}
var_dump(BreakCSS($css));

//see its same

【讨论】:

    【解决方案5】:

    除了 Gabriel Anderson 对处理 css @media 查询、子选择器 &gt; 、base64 图像和 input[type="button"]:hover 的回答之外

    function parse_css_selectors($css,$media_queries=true){
    
        $result = $media_blocks = [];
    
        //---------------parse css media queries------------------
    
        if($media_queries==true){
    
            $media_blocks=parse_css_media_queries($css);
        }
    
        if(!empty($media_blocks)){
    
            //---------------get css blocks-----------------
    
            $css_blocks=$css;
    
            foreach($media_blocks as $media_block){
    
                $css_blocks=str_ireplace($media_block,'~£&#'.$media_block.'~£&#',$css_blocks);
            }
    
            $css_blocks=explode('~£&#',$css_blocks);
    
            //---------------parse css blocks-----------------
    
            $b=0;
    
            foreach($css_blocks as $css_block){
    
                preg_match('/(\@media[^\{]+)\{(.*)\}\s+/ims',$css_block,$block);
    
                if(isset($block[2])&&!empty($block[2])){
    
                    $result[$block[1]]=parse_css_selectors($block[2],false);
                }
                else{
    
                    $result[$b]=parse_css_selectors($css_block,false);
                }
    
                ++$b;
            }
        }
        else{
    
            //---------------escape base64 images------------------
    
            $css=preg_replace('/(data\:[^;]+);/i','$1~£&#',$css);
    
            //---------------parse css selectors------------------
    
            preg_match_all('/([^\{\}]+)\{([^\}]*)\}/ims', $css, $arr);
    
            foreach ($arr[0] as $i => $x){
    
                $selector = trim($arr[1][$i]);
    
                $rules = explode(';', trim($arr[2][$i]));
    
                $rules_arr = [];
    
                foreach($rules as $strRule){
    
                    if(!empty($strRule)){
    
                        $rule = explode(":", $strRule,2);
    
                        if(isset($rule[1])){
    
                            $rules_arr[trim($rule[0])] = str_replace('~£&#',';',trim($rule[1]));
                        }
                        else{
                            //debug
                        }
                    }
                }
    
                $selectors = explode(',', trim($selector));
    
                foreach ($selectors as $strSel){
    
                    if($media_queries===true){
    
                        $result[$b][$strSel] = $rules_arr;
                    }
                    else{
    
                        $result[$strSel] = $rules_arr;
                    }
                }
            }
        }
        return $result;
    }
    
    function parse_css_media_queries($css){
    
        $mediaBlocks = array();
    
        $start = 0;
        while(($start = strpos($css, "@media", $start)) !== false){
    
            // stack to manage brackets
            $s = array();
    
            // get the first opening bracket
            $i = strpos($css, "{", $start);
    
            // if $i is false, then there is probably a css syntax error
            if ($i !== false){
    
                // push bracket onto stack
                array_push($s, $css[$i]);
    
                // move past first bracket
                $i++;
    
                while (!empty($s)){
    
                    // if the character is an opening bracket, push it onto the stack, otherwise pop the stack
                    if ($css[$i] == "{"){
    
                        array_push($s, "{");
                    }
                    elseif ($css[$i] == "}"){
    
                        array_pop($s);
                    }
    
                    $i++;
                }
    
                // cut the media block out of the css and store
                $mediaBlocks[] = substr($css, $start, ($i + 1) - $start);
    
                // set the new $start to the end of the block
                $start = $i;
            }
        }
    
        return $mediaBlocks;
    }
    

    资源

    【讨论】:

      【解决方案6】:

      这是一个使用正则表达式的快速而肮脏的独立黑客:

      $input = '
      #stuff {
          background-color: red;
      }
      
      #content.postclass-subcontent {
          background-color: red;
      }
      
      #content2.postclass-subcontent2 {
          background-color: red;
      }
      ';
      
      $cssClassName = 'postclass';
      preg_match_all('/(#[a-z0-9]*?\.?'.addcslashes($cssClassName, '-').'.*?)\s?\{/', $input, $matches);
      var_dump($matches[1]);
      

      结果:

      array(2) {
        [0]=>
        string(29) "#content.postclass-subcontent"
        [1]=>
        string(31) "#content2.postclass-subcontent2"
      }
      

      【讨论】:

      • 如果你有逗号分隔的选择器怎么办?还是逗号和换行符分隔的选择器?
      • 永远不要使用正则表达式来解析语言。当我一无所有时,我确实使用了一个正则表达式来为所有选择器添加一个 ID,但即使有这个怪物,我也不断收到误报和误报,我必须使用其他正则表达式或手动更正。 (?&lt;![-\w:\s@\({+'\.^])(\s*)([\^*&gt;\w\s\:\(\)\[\]\=\"\.-]+)(?=[,\{])
      • 正则表达式最适合正则语言。这可能有效,但如果 postclass 出现在规则的右侧,则会失败。例如.explain:before { content: 'uses #my_id.postclass-... in order to specify target classes'; }.
      猜你喜欢
      • 2012-06-22
      • 2014-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-12
      • 2015-08-19
      • 2011-06-20
      • 2012-01-10
      相关资源
      最近更新 更多