4

I have such an inline CSS like this

color:#777;font-size:16px;font-weight:bold;left:214px;position:relative;top:70px

The CSS may end with a semicolon ";" or not. It also can contain extra space between its values. I'm about using "explode" function to parse the CSS into an array, something like :

Array(
"color" => "#777",
"font-size" => "16px",
"font-weight" => "bold",

and so on.

Can anybody suggest me a way to use regular expression to complete this task?

Teiv
  • 2,605
  • 10
  • 39
  • 48
  • 1
    possible duplicate of [Parsing CSS by regex](http://stackoverflow.com/questions/236979/parsing-css-by-regex) – Gordon Dec 13 '10 at 18:49
  • 1
    Thanks for the link but its topic is about parsing the whole CSS file or CSS within "style" tag with selectors. I'm about parsing inline CSS only which is in the "style" attribute of an element. – Teiv Dec 13 '10 at 19:01

5 Answers5

6

Another way, using a regex:

$css = "color:#777;font-size:16px;font-weight:bold;left:214px;position:relative;top:   70px";

$results = array();
preg_match_all("/([\w-]+)\s*:\s*([^;]+)\s*;?/", $css, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
  $results[$match[1]] = $match[2];
}

print_r($results);

Outputs:

Array
(
    [color] => #777
    [font-size] => 16px
    [font-weight] => bold
    [left] => 214px
    [position] => relative
    [top] => 70px
)
gnarf
  • 105,192
  • 25
  • 127
  • 161
  • Just to be clear, this pattern may require that the values be left trimmed due to that greedy negated character class. https://3v4l.org/6V4nj – mickmackusa Feb 06 '20 at 08:23
4

Here's a quick-and-dirty script that does what you're asking:

<?php

$css = "color:#777;font-size:16px;font-weight:bold;left:214px;position:relative;top:   70px";

$attrs = explode(";", $css);

foreach ($attrs as $attr) {
   if (strlen(trim($attr)) > 0) {
      $kv = explode(":", trim($attr));
      $parsed[trim($kv[0])] = trim($kv[1]);
   }
}
?>

And the output of print_r($parsed) is:

Array
(
   [color] => #777
   [font-size] => 16px
   [font-weight] => bold
   [left] => 214px
   [position] => relative
   [top] => 70px
)
gnuf
  • 2,722
  • 1
  • 25
  • 32
  • 2
    This would break with: `background-image: url(/example.jpeg?arg=1;arg=2);`. Regular expressions are not a good choice for parsing non-regular data. – Quentin Dec 13 '10 at 20:14
  • @David Dorward - Sure - that case would break this solution, or any other "simple" parser that you wrote, but this answer doesn't use regular expressions ... Just plain old `explode`'s - Perhaps you should direct the RE hate somewhere else this time ;) – gnarf Dec 13 '10 at 20:18
  • Ooops. That's teach me to assume that it actually answers the question ;) It still suffers from the same problem though. You need a proper CSS parser to parse CSS. – Quentin Dec 13 '10 at 20:20
  • Actually Regex is a bit faster than using "explode" in this situation and I asked for a Regex solution so I still vote for gnarf's answer. Nevertheless, thank you all very much for the answer :) – Teiv Dec 14 '10 at 09:07
0

I had issues with the regex solution, and the quick and dirty php explode solution fails with urls, so here is another non-regex solution that doesn't fail with urls:

$css = 'background-image:url(https://test.com/media.jpg);color:#777;font-size:16px;font-weight:bold;left:214px;position:relative;top:70px';

$attrs = explode(';', $css);
$parsed = [];
foreach($attrs as $attr) {
  $first_colon_pos = strpos($attr, ':');
  $key = substr($attr, 0, $first_colon_pos);
  $value = substr($attr, $first_colon_pos + 1);
  $parsed[$key] = $value;
}

Outputs:

Array
(
    [background-image] => url(https://test.com/media.jpg)
    [color] => #777
    [font-size] => 16px
    [font-weight] => bold
    [left] => 214px
    [position] => relative
    [top] => 70px
)

Felix Eve
  • 3,811
  • 3
  • 40
  • 50
0

In case of someone who's looking for something without a loop there's this solution.

Use case: string from HTML style attribute (needed for Behat Tests for example)

$styleAttribute = "color: blue; opacity: 50%;";
$styleAsKeyValuePairs = array_column(array_chunk(preg_split("/[:;]\s*/", $styleAttribute), 2), 1, 0);

print_r($styleAsKeyValuePairs);

Hope this whould be helpful !

Delphine
  • 861
  • 8
  • 21
-1

Let try this it will work fine

str.replace(/(\w+[-]?\w+)(?=:)/gi,'\n[$1] => ').replace(/[:;]+/g,'')
4b0
  • 21,981
  • 30
  • 95
  • 142