I need to parse some CSS code like:
color: black;
font-family:"Courier New";
background:url('test.png');
color: red;
--crap;
Into:
array (
'color'=>'red',
'font-family'=>'"Courier New"',
'background'=>'url(\'test.png\')',
'--crap'=>''
)
I need to do this via PHP. I can see this done easily via regexp (well, easy to those that know it, unlike myself :-) ).
I need the resulting array to be "normalized", there should not be any trailing spaces between tokens, even if they were in the source.
Valueless css tokens should be included in the array as a key only. (see --crap)
Quotes (and values in general) should remain as is, except for extra formatting (spaces, tabs); easily removed via trim() or via the relevant regexp switch.
Please not that at this point, I specifically do not need a full CSS parser, ie, there is no need to parse blocks ( {...} ) or selectors ( a.myclass#myid ).
Oh, and considering I'll be putting this stuff in an array, it is perfectly ok if the last items ( color:red; ) completely override the original items ( color:black; ).
Here's a simple version:
$a = array();
preg_match_all('/^\s*([^:]+)(:\s*(.+))?;\s*$/m', $css, $matches, PREG_SET_ORDER);
foreach ($matches as $match)
$a[$match[1]] = isset($match[3]) ? $match[3] : null;
Sample output:
array(4) {
["color"]=>
string(3) "red"
["font-family"]=>
string(13) ""Courier New""
["background"]=>
string(15) "url('test.png')"
["--crap"]=>
NULL
}
Not tested with anything except your source data, so I'm sure it has flaws. Might be enough to get you started.
I found this few weeks back and looks interesting.
http://websvn.atrc.utoronto.ca/wsvn/filedetails.php?repname=atutor&path=/trunk/docs/include/classes/cssparser.php
Example:
$Parser = new cssparser();
$Results = $Parser->ParseStr("color: black;font-family:"CourierNew";background:url('test.png');color: red;--crap;");
Why don't take a look at CSSTidy?
You can try:
$result = array();
if(preg_match_all('/\s*([-\w]+)\s*:?\s*(.*?)\s*;/m',$input,$m))
var_dump($m);
// $m[1] contains all the properties
// $m[2] contains their respective values.
for($i=0;$i<count($m[1]);$i++) {
$result[$m[1][$i]] = $m[2][$i];
}
}
Related
I have a simple php code which changes the order of the name inside an array.
$arr = [
"Meier, Peter",
"Schulze, Monika",
"Schmidt, Ursula",
"Brosowski, Klaus",
];
foreach($arr as $name => $name2)
{
$vname = explode(", ", $name2);
$new = array_reverse($vname);
$arr[$name] = implode(", ", $new);
}
echo "<pre>".print_r($arr, true)."</pre>";
Basically I would like the edit the code, that the source code displays the array not in one line, but in several lines (one for each Firstname + Lastname) like shown below:
Array
(
[0] => Peter, Meier
[1] => Monika, Schulze
[2] => Ursula, Schmidt
[3] => Klaus, Brosowski
)
Right now the source code shows the excelpt same result, but only in one line. Is it possible to adapt the print_r command in this way?
Best Regards
Edit for clarification:
my code gives as a result the array which I have also posted in my question. In the html source code, the same array is in one line[0] => Peter, Meier [1] => Monika, Schulze and so on. So there is a difference between the way my result is structured and how the source code is structured. I would like to change the source code structure of the array, that it looks like the actual result.
You can adopt the line_breaks from print_r for html with the function nl2br()
echo nl2br(print_r($arr, true));
or you build a List function with
echo '<ul>'.PHP_EOL;
foreach($arr as $name){
echo "<li>{$name}</li>".PHP_EOL;
}
echo '</ul>'.PHP_EOL;
I think I found out what you were trying to say:
output is based on https://3v4l.org/LLvZW from #tcj
When printing with print_r your output looks like this:
When you inspect your HTML elements in your browser your inspector shows this:
(Note: everything is in one line)
The clarifications:
the output looks like this because <pre> does set a fixed width, and white-space: pre;
If you remove white-space: pre; you should end with an output like this:
If you inspect your element in the browser, it will still all be in one line
HOWEVER, if you try to edit the element inside your browser inspector then it WON'T be in one line.
So my answer to this is, that I assume this is some optimization done by the browser.
Probably so you can see more of the other HTML you have, or for other reasons...
(Im on Firefox btw.)
I'll have code embedded in HTML, it will look something like this:
<div id="someDiv">
{:
HTMLObject
id: form
background: blue
font: large
fields [
username: usr
password: pwd
]
foo: bar
:}
</div>
I am trying to write a regular expression that will take these HTMLObjects and break them into manageable arrays. I already have the regexp that will do the lines such as
id: form
However, I'm having trouble with making the regexp also match ones like
fields [
username: usr
password: pwd
]
Here is the function I have that performs these tasks:
function parseHTMLObjects($html) {
$details = preg_replace('/[{:]([^}]+):}/i', '$1', $html);
$details = trim(str_replace('HTMLObject', '', $details));
$dynamPattern = '/([^\[]+)\[([^\]]+)]/';
$dynamMatch = preg_match_all($dynamPattern, $details, $dynamMatches);
print_r($dynamMatches); // nothing is shown here
$findMatch = preg_match_all('/([^:]+):([^\n]+)/', $details, $matches);
$obs = array();
foreach($matches[0] as $o) {
$tmp = trim($o);
echo $tmp . "\n";
}
}
When I pass an HTML string like I demonstrated at the beginning of the page, the $findMatch regexp works fine, but nothing gets stored in the dynams one. Am I going about this in the wrong way?
Basically all I need is each object stored in an array, so from the sample HTML string above, this would be an ideal array:
Array() {
[0] => id: form
[1] => background: blue
[2] => font: large
[3] => fields [
username: usr
password: pwd
]
[4] => foo: bar
}
I have all the sorting and manipulation handled beyond that point, but like I said, I'm having trouble getting the same regexp that handles the colon style objects to also handle the bracket style objects.
If I need to use a different regexp and store the results in a different array that is fine too.
It would be easly made with some black sorcery called YAML or JSON with these syntaxes:
YAML
{:
HTMLObject:
id: form
background: blue
font: large
fields: [
username: usr,
password: pwd
]
foo: bar
:}
JSON
{:
{
"HTMLObject":{
"id": "form",
"background": "blue",
"font": "large",
"fields": [
{"usernamd": "usr"},
{"password": "pwd"}
],
"foo": "bar"
}
}
:}
Bu-bu-but why? 'Cuz it's natively parsed. No dirty RegExps.
I can't comment on posts yet, but definitely looking for conversion functions from one notation to php arrays is the way forward, json_decode is one, though your data is starting life as something else.
regex can be very tricky with complicated data that is often complex because it has some other structure to it that is better interpreted with other tools
PS if you do use json_decode in php at any point, don't get caught out by the second parameter - it needs to be set to 'true' to get an array !
I want to fetch text in array between all <span> </span> tag from HTML, I have tried with this code but it returns only one occurrence :
preg_match('/<span>(.+?)<\/span>/is', $row['tbl_highlighted_icon_content'], $matches);
echo $matches[1];
My HTML:
<span>The wish to</span> be unfairly treated is a compromise attempt that would COMBINE attack <span>and innocen</span>ce. Who can combine the wholly incompatible, and make a unity of what can NEVER j<span>oin? Walk </span>you the gentle way,
My code returns only one occurrence of span tag, but I want get all text from every span tag in HTML in the form of a php array.
you need to switch to preg_match_all function
Code
$row['tbl_highlighted_icon_content'] = '<span>The wish to</span> be unfairly treated is a compromise attempt that would COMBINE attack <span>and innocen</span>ce. Who can combine the wholly incompatible, and make a unity of what can NEVER j<span>oin? Walk </span>you the gentle way,';
preg_match_all('/<span>.*?<\/span>/is', $row['tbl_highlighted_icon_content'], $matches);
var_dump($matches);
as you can see now array is correctly populated so you can echo all your matches
use preg_match_all() it's the same, it will return all the occurrences in the $matches array
http://php.net/manual/en/function.preg-match-all.php
here is code to get all span value in array
$str = "<span>The wish to</span> be unfairly treated is a compromise
attempt that would COMBINE attack <span>and innocen</span>ce.
Who can combine the wholly incompatible, and make a unity
of what can NEVER j<span>oin? Walk </span>you the gentle way,";
preg_match_all("/<span>(.+?)<\/span>/is", $str, $matches);
echo "<pre>";
print_r($matches);
you output will be
Array
(
[0] => Array
(
[0] => The wish to
[1] => and innocen
[2] => oin? Walk
)
[1] => Array
(
[0] => The wish to
[1] => and innocen
[2] => oin? Walk
)
)
you can use o or 1 index
If you don't mind using a third-party component, I'd like to show you Symfony's DomCrawler component. It 's a very simple way to parse HTML/XHTML/XML files and navigate through the nodes.
You can even use CSS Selectors. Your code would be something like:
$crawler = new Crawler($html);
$spans = $crawler->filter("span");
echo $spans[1]->getText();;
You don't even need to have a full HTML/XML document, if you assign only the <span>...</span> part of your code, it'll work fine.
I have the following which works great, but now what I want to do is if a user types [MAP] then I want to get the word MAP
I also want allow users to send things like [MAP = array("LOCATION"=>"Melbourne Australia")]
and for the PHP to make map a array so I can then send it to a function later on
I currently do the following
$map = strpos($stringtocheck, "[MAP]");
But the issue here, is if we have a number of [] with different insides like [BOLD], [INSERT] etc then it wont find it and put it in its own $
and also it means we need to know what the array is field with or anything like that
A simple regex will pull info out of square brackets:
$s = 'Yo be [diggin] [my leet] scriptzors!';
$matches = null;
preg_match_all('/\[(.*?)\]/', $s, $matches);
var_dump($matches[1]);
Result:
array(2) {
[0]=>
string(6) "diggin"
[1]=>
string(7) "my leet"
}
Example: http://codepad.viper-7.com/erBpuB
I have an array ($form) which retreives some information from $_POST:
$form = $_POST['game'];
Now I want to work with the values in this array, but I somehow fail.
For debugging I used these commands (in the exact same order, with no extra lines inbetween):
print_r($form);
echo '#' . $form['System_ID'] . "#";
and as returned output I get:
Array
(
['Title'] => Empire: Total War - Special Forces
['Genre_ID'] => 1
['Type'] => Spiel
['System_ID'] => 1
)
##
Any ideas where my System_ID went? It's there in print_r, but not in the next line for echo?!?
Alright, I found the solution myself (a.k.a. d'oh!)
I added another
var_dump($form);
for further analysis and this is what I got:
array(4) {
["'Title'"]=>
string(34) "Empire: Total War - Special Forces"
["'Genre_ID'"]=>
string(1) "1"
["'Type'"]=>
string(5) "Spiel"
["'System_ID'"]=>
string(1) "1"
}
Notice the single quote inside the double quote?
Looks as if you're not allowed to use the single quote in html forms or they will be included in the array key:
Wrong: <input type="text" name="game['Title']" />
Correct: <input type="text" name="game[Title]" />
print_r() doesn't put quotes around keys - for debugging i'd recommend ditching print_r altogether. var_export or var_dump are better.
even better: use firephp. it sends the debug info via headers, so it doesn't mess up your output and thus is even usable with ajax. output is displayed nicely with firebug including syntax coloring for data structures.
and it's even easier to use: just fb($myvar);
It works for me:
<?
$form['System_ID'] = 1;
print_r($form);
echo '#' . $form['System_ID'] . '#';
?>
Output:
% php foo.php
Array
(
[System_ID] => 1
)
#1#
PHP 5.2.6, on Fedora Core 10
EDIT - note that there's a hint to the real cause here. In my code the print_r output (correctly) shows the array keys without single quotes around them. The original poster's keys did have quotes around them in the print_r output, showing that somehow the actual key contained the quote marks.