Can i parse a plist file with php and kind of get it into an array, like the $_POST[''] so i could call $_POST['body'] and get the string that has the <key> body ?
CFPropertyList - A PHP Implementation Of Apple's plist (PropertyList)
Googling for "php plist parser" turned up this blog post that seems to be able to do what you are asking for.
Took a look at some of the libraries out there but they have external requirements and seem overkill. Here's a function that simply puts the data in to associative arrays. This worked on a couple of exported itunes plist files I tried.
// pass in the full plist file contents
function parse_plist($plist) {
$result = false;
$depth = [];
$key = false;
$lines = explode("\n", $plist);
foreach ($lines as $line) {
$line = trim($line);
if ($line) {
if ($line == '<dict>') {
if ($result) {
if ($key) {
// adding a new dictionary, the line above this one should've had the key
$depth[count($depth) - 1][$key] = [];
$depth[] =& $depth[count($depth) - 1][$key];
$key = false;
} else {
// adding a dictionary to an array
$depth[] = [];
}
} else {
// starting the first dictionary which doesn't have a key
$result = [];
$depth[] =& $result;
}
} else if ($line == '</dict>' || $line == '</array>') {
array_pop($depth);
} else if ($line == '<array>') {
$depth[] = [];
} else if (preg_match('/^\<key\>(.+)\<\/key\>\<.+\>(.+)\<\/.+\>$/', $line, $matches)) {
// <key>Major Version</key><integer>1</integer>
$depth[count($depth) - 1][$matches[1]] = $matches[2];
} else if (preg_match('/^\<key\>(.+)\<\/key\>\<(true|false)\/\>$/', $line, $matches)) {
// <key>Show Content Ratings</key><true/>
$depth[count($depth) - 1][$matches[1]] = ($matches[2] == 'true' ? 1 : 0);
} else if (preg_match('/^\<key\>(.+)\<\/key\>$/', $line, $matches)) {
// <key>1917</key>
$key = $matches[1];
}
}
}
return $result;
}
Related
I hope the title is self explanatory.
I would like to loop over a xml file line by line, then match a particular line (getting attributes from that line), then get the next X lines after that line.
I have the following code, which attempts to do this, but I cant seem to figure out how to get the next X lines after.
$file = 'Electric.xml';
$lines = file($file);//file in to an array
foreach($lines as $line){
$reads = element_attributes('WINDOW',$line);
if($reads['class'] == 'Bracelets'){
print_r($reads);
}
if($reads['class'] == 'Handbags'){
print_r($reads);
}
}
function element_attributes($element_name, $xml) {
if ($xml == false) {
return false;
}
// Grab the string of attributes inside an element tag.
$found = preg_match('#<'.$element_name.
'\s+([^>]+(?:"|\'))\s?/?>#',
$xml, $matches);
if ($found == 1) {
$attribute_array = array();
$attribute_string = $matches[1];
// Match attribute-name attribute-value pairs.
$found = preg_match_all(
'#([^\s=]+)\s*=\s*(\'[^<\']*\'|"[^<"]*")#',
$attribute_string, $matches, PREG_SET_ORDER);
if ($found != 0) {
// Create an associative array that matches attribute
// names to attribute values.
foreach ($matches as $attribute) {
$attribute_array[$attribute[1]] =
substr($attribute[2], 1, -1);
}
return $attribute_array;
}
}
// Attributes either weren't found, or couldn't be extracted
// by the regular expression.
return false;
}
Use a proper parser, like SimpleXML, to parse the file. Then your issue becomes trivial. The PHP manual contains a tutorial to help you get started.
In this case you just loop over the lines, checking the property of the tag you're looking for, until you find a match. Then, loop over the next # elements, saving them into an array.
Something like this:
$xml = new SimpleXML ("file.xml");
foreach ($xml->node->element as $element) {
if ($element->attribute != "match") {
continue;
}
// If we get here we want to save the next # lines/elements.
}
$linesLength = count($lines);
$XLines = array();
for($index = 0; $index < $linesLength; $index++){
$reads = element_attributes('WINDOW',$line);
if($reads['class'] == 'Bracelets'){
print_r($reads);
$XLines[] = array_slice($array, $index, $X);
$index += $X;
}
if($reads['class'] == 'Handbags'){
print_r($reads);
$XLines[] = array_slice($array, $index, $X);
$index += $X;
}
}
I'm working on a searchmachine for my blog (http://iljalicious.net/suche/) and I'm sorry that the used language is not English on the website but I translated the code for you:
$lookingfor = $_POST['word'];
$lines = file('../archiv/2015/juli/eintraege.dat');
$found = false;
foreach($lines as $line)
{
if(strpos($line, $lookingfor) !== false)
{
$found = true;
echo $line;
}
}
if(!$found)
{
echo 'I found nothing, dood!';
}
Currently, the function is working perfectly, but only if it is looking for a word in one file ('http://iljalicious.net/archiv/2015/juli/eintraege.dat').
On my blog, I have such a file for every month and I want my searchmachine to look for a word in every file called 'eintraege.dat' in the directory '../archiv/' and subdirectories as '2015','2016' etc.
How can I solve this problem?
Greetings, iljalicious
****EDIT*****
Found another..kind of stupid solution:
The code is not translated, but is the same as above, the only thing I changed was:
From:
$lines = file('../archiv/2015/juli/eintraege.dat');
To:
$archiv = file('../suche/archiv.php');
And it worked.
$suchbegriff = $_POST[suchbegriff];
$archiv = file('../suche/archiv.php');
$gefunden = false;
foreach($archiv as $zeile)
{
if(strpos($zeile, $suchbegriff) !== false)
{
$gefunden = true;
echo $zeile;
}
}
if(!$gefunden)
{
echo '<div class="information">'.
'Alter, wonach hast du gesucht?<br>'.
'Mhm... Soso, <a>'. $_POST[suchbegriff].
'</a> also! '.
'Dein Ernst?<br>'.
'Als ob ich über sowas berichte O;'.
'</div>';
}
You can try using glob,
The glob() function searches for all the pathnames matching pattern
according to the rules used by the libc glob() function, which is
similar to the rules used by common shells.
Something similar to this:
$file_list = [];
foreach (glob("archive*/eintraege.dat") as $filename) {
$file_list[] = $filename;
}
$lookingfor = $_POST['word'];
foreach ($file_list as $file) {
$lines = $file;
$found = false;
foreach ($lines as $line) {
if (strpos($line, $lookingfor) !== false) {
$found = true;
echo $line;
}
}
if (!$found) {
echo 'I found nothing, dood!';
}
}
Note: glob work only with files hosted on your server.
So if you want to search from the root of your server, the function argument should be something like : /var/www/site/content/archieve/*/eintraege.dat
if you want to search in the same folder of your file:
*/eintraege.dat
in my code i need to get both operator and the values to do my calculation. my code is,
$demension = "3.5x2.3=>4.8x8.9"
public function searchItems($dimension)
{
$out= preg_split('/[x-]/', $dimension);
$i=0;
foreach ($out as $key) {
preg_match('/(!=|=|<=|<|>=|>)/',$key,$matches);
if(!empty($matches))
{
$result[$i]=$matches;
}else
{
$result[$i]=$key;
}
$i++;
}
return $result;
}
I need to get 3.5,2.3,=>,4.8,8.9 separately
can any one show me the right path.
Here it is. Using a regexp to get values and operators.
function getParts($string)
{
$regexp = "/(\d+?\.\d+?)|([<>=]+)/";
$parts = [];
if (preg_match_all($regexp, $string, $matches)) {
$parts = $matches[0];
}
return $parts;
}
$dimension = "3.5x2.3=>4.8x8.9"
print_r(getParts($dimension));
I am developing a system that searches for words that the user types in php files, using PHP without MySQL but I am having a problem. The system works really well when there is not a line break in the file. For example, if I search for the word "good" in a file that contains the text "good morning" works fine, but if I search for "good" in a file that contains the text "goodmorning" (with a line break) it won't list the file as a result. Here is my code:
index.php
<form action="busca.php" method="get">
<input type="text" name="s"><br>
<input type="submit">
</form>
busca.php
<?php
$pesq = (isset($_GET['s'])) ? trim($_GET['s']) : '';
if (empty($pesq)) {
echo 'Type something.';
} else {
$index = "index.php";
$busca = glob("posts/content/*.php", GLOB_BRACE);
$lendo = "";
$conteudo = "";
foreach ($busca as $item) {
if ($item !== $index) {
$abrir = fopen($item, "r");
while (!feof($abrir)) {
$lendo = fgets($abrir);
$conteudo .= $lendo;
$lendo .= strip_tags($lendo);
}
if (stristr($lendo, $pesq) == true) {
$dados = str_replace(".php", "", $item);
$dados = basename($dados);
$result[] = "$dados";
unset($dados);
}
fclose($abrir);
}
}
if (isset($result) && count($result) > 0) {
$result = array_unique($result);
echo '<ul>';
foreach ($result as $link) {
echo "<li>$link</li>";
}
echo '</ul>';
} else {
echo 'No results';
}
}
?>
Your usage of stristr is incorrect.
Compare it with false like this:
if (stristr($lendo, $pesq) !== false) {
If a string is located — the function returns the substring. Which can be casted as boolean true or false, you never know. If it doesn't find it — it returns false — the only correct value you should compare it to.
Even better to use strpos for this.
My variant:
foreach ($busca as $item) {
if ($item !== $index) {
$lendo = file_get_contents($item);
$lendo = strip_tags($lendo);
if (strpos($lendo, $pesq) !== false) {
$dados = str_replace(".php", "", basename($item));
$result[] = "$dados";
}
}
}
To fix the linebreaks - try to get rid of them
Like this:
$lendo = file_get_contents($item);
$lendo = strip_tags($lendo);
$lendo = str_replace(["\r","\n"], ' ', $lendo);
I have a simple data format that goes as follows:
stuff/stuff/stuff
An example would be:
data/test/hello/hello2
In order to retrieve a certain piece of data, one would use my parser, which tries to do the following:
In data/test/hello/hello2
You want to retrieve the data under data/test (which is hello). My parser's code is below:
function getData($data, $pattern)
{
$info = false;
$dataLineArray = explode("\n", $data);
foreach($dataLineArray as &$line)
{
if (strpos($line,$pattern) !== false) {
$lineArray = explode("/", $line);
$patternArray = explode("/", $pattern);
$iteration = 0;
foreach($lineArray as &$lineData)
{
if($patternArray[$iteration] == $lineData)
{
$iteration++;
}
else
{
$info = $lineData;
}
}
}
}
return $info;
}
However, it always seems to return the last item, which in this case is hello2:
echo getData("data/test/hello/hello2", "data/test");
Gives Me;
hello2
What am I doing wrong?
If you want the first element after the pattern, put break in the loop:
foreach($lineArray as $lineData)
{
if($patternArray[$iteration] == $lineData)
{
$iteration++;
}
elseif ($iteration == count($patternArray))
{
$info = $lineData;
break;
}
}
I also check $iteration == count($patternArray) so that it won't return intermediate elements, e.g.
/data/foo/test/hello/hello2
will return hello rather than foo.
P.S. There doesn't seem to be any reason to use references instead of ordinary variables in your loops, since you never assign to the reference variables.