I have a code that removes only the xml tags that expired and list the other tags, but if one tag expired it will delete it and stop the foreach loop execution without listing the other tags. if I reload the page after the code finished removing the expired tag it will list the other tags normally without any problem. how can I make it continue to list the other tags?
php code:
$xml_file = simplexml_load_file("xml_file.xml");
foreach ($xml_file as $item)
{
$current_date = time();
$article_date = (int)$item->date;
$item_number = (int)str_replace("a" , "" ,$item->getName());
if ($current_date >= $article_date + 100000)
{
if ($item->children()->getName() == "a")
{
$dom = dom_import_simplexml($item);
$dom->parentNode->removeChild($dom);
$return = simplexml_import_dom($dom);
$xml_file->asXML('xml_file.xml');
unlink('file.html');
}
}
elseif ($current_date < $article_date + 100000)
{
echo 'hello';
}
}
xml code:
<articles>
<a1><a>gr</a><date>14</date></a1>
<a2><a>gr</a><date>1414141414141414</date></a2>
<a3><a>gr</a><date>1414141414141414</date></a3></articles>
this code should remove the first tag and print hello twice, but it just removes the first tag and stop the foreach loop execution without printing any thing, and if I reload the page after deleting the first tag it prints hello twice without any problem.
Some lines are commented as their purpose is unclear ... You can remove, but not with foreach loop and you have to start from the end... otherwise it is like removing the chair under yourself - loop is unclear, whether it should start with the 'new' $item, or jump over it.
$children = $xml_file->children();
for($i = count($children) - 1; $i >= 0; $i--)
{
$item = $children[$i];
$current_date = time();
$article_date = (int)$item->date;
$item_number = (int)str_replace("a" , "" ,$item->getName());
if ($current_date >= $article_date + 100000)
{
if ($item->children()->getName() == "a")
{
$dom = dom_import_simplexml($item);
$dom->parentNode->removeChild($dom);
// $return = simplexml_import_dom($dom);
// $xml_file->asXML('xml_file.xml');
// unlink('file.html');
}
}
elseif ($current_date < $article_date + 100000)
{
echo 'hello';
}
}
var_dump($xml_file);
Another way to remove child without conversion to DOM is
$children = &$xml_file->children();
// the rest is the same, but replace
// $dom = dom_import_simplexml($item);
// $dom->parentNode->removeChild($dom);
// with
unset($children[$i]);
Related
I have a script that reads values in an external XML file using PHPExcel.php, then it prints results reading the last time a number is $extraset is found into the XML file.
My problem : i should reverse the way the script calculates the result, since my values go from the newer to the older.
Example : if the 10 value appears in row 2 and then in row 6, correct result should be : 10 appears in row 2. At the moment I get '10 appears in row 10'.
Is there a way to reverse the way phpexcel read the file ? Or maybe i can just reverse the way values are processed ? Here is the script :
<?php
require_once "Classes/PHPExcel.php";
$path = "original_source.xls";
$reader = PHPExcel_IOFactory::createReaderForFile($path);
$excel_Obj = $reader->load($path);
//Get the last sheet in excel
//$worksheet=$excel_Obj->getActiveSheet();
//Get the first sheet in excel
$worksheet=$excel_Obj->getSheet('0');
$lastRow = $worksheet->getHighestRow();
$columncount = $worksheet->getHighestDataColumn();
$columncount_number = PHPExcel_Cell::columnIndexFromString($columncount);
$row_start = 6;
$row_end = 26;
$col_start = 2; //Index of column - C
$col_end = 21; //Index of column - V
$sets = array();
for ($row = 0; $row <= $lastRow; $row++) {
$set = array();
for ($col = 0; $col <= $columncount_number; $col++) {
if ($row >= $row_start && $row <= $row_end && $col >= $col_start && $col <= $col_end) {
array_push($set, $worksheet->getCell(PHPExcel_Cell::stringFromColumnIndex($col).$row)->getValue());
}
else if ($row > $row_end) {
break;
}
}
if ($row >= $row_start && $row <= $row_end) {
array_push($sets, $set);
}
else if ($row > $row_end) {
break;
}
}
//echo '<pre>'; print_r($sets); die;
$extraset = ['113', '15', '313'];
$reverse_sets = array_reverse($sets);
foreach ($extraset as $element) {
foreach ($reverse_sets as $index => $set) {
if (in_array($element, $set)) {
$actual_index = count($reverse_sets)-$index-1;
echo "Extraset element '$element' is in set $actual_index<br>";
break;
}
}
}
?>
I was trying with array_reverse, but I only keep getting 'error 500'. I'm a bit confused.
Thanks for your help
EDIT :
The modify i did with array reverse was to remove the array reverse function, changing that part in this way, and it works properly :
foreach ($extraset as $element) {
foreach ($sets as $index => $set) {
if (in_array($element, $set)) {
$actual_index = count($sets)-$index-1;
echo "Extraset element '$element' is in set $actual_index<br>";
break;
}
}
}
?>
Now the script outputs me the right value, but what I can't fix is the way $actual_index works.
This is my actual output :
Extraset element '113' is in set 0
Extraset element '15' is in set 20
Extraset element '313' is in set 20
My problem :
The way it search the values is correct, but is wrong the way it calculates the set. Set 0 should be set 20, while set 20 should be set 0.
I have a script to get certain data from a page based on the content of a span ID
However there are 200+ pages of results to trawl through and it only displays 127 results on each page
The script I have does get data for the 127 elements that are on the first page however it wont then open the new page and continuing to get data
It just stops after the initial 127
Any help would be great
$end = 200;
$start = 1;
$stop = $start + 10;
$html = file_get_contents('http://example.com/res/'.$start);
$doc = new DOMDocument();
#$doc->loadHTML($html);
echo $stop;
$i = 0;
foreach($doc->getElementsByTagName('span') as $element ) { //Loops through all available span elements
if (!empty($element->attributes->getNamedItem('id')->value)) { // Discards irrelevant span elements based on their `ID`. A similar sorting is achieved with `empty()` as the target `span` doesn't have any associated `ID`.
echo "Record : ".$i.' '. $element->attributes->getNamedItem('id')->value."\n";
$i++;
$end = $start;
}
}
if($i == 127) {
$i = 0;
do {
$next = $start++;
$page = $next;
$html = file_get_contents('http://example.com/res/'.$page);
$doc = new DOMDocument();
#$doc->loadHTML($html);
foreach($doc->getElementsByTagName('span') as $element )
{
if (!empty($element->attributes->getNamedItem('id')->value))
{
echo "Record : ".$i.' '. $element->attributes->getNamedItem('id')->value."\n";
$i++;
$end = $start;
}
}
} while ($page != $stop);
//echo $i.' Records';
}
As stated in comments, since your last record displayed in the first loop is 127, the line after that echo increments $i from 127 to 128.
foreach($doc->getElementsByTagName('span') as $element ) { //Loops through all available span elements
if (!empty($element->attributes->getNamedItem('id')->value)) { // Discards irrelevant span elements based on their `ID`. A similar sorting is achieved with `empty()` as the target `span` doesn't have any associated `ID`.
echo "Record : ".$i.' '. $element->attributes->getNamedItem('id')->value."\n";
$i++; //At last iteration, $i = 128
$end = $start;
}
}
And then, if($i == 127) will be false.
I suggest you to change the condition to if($i >= 127)
I m trying to parse a post related statement from a forum site using PHP dom parser. It works when we insert individual url's of the page, but when we try to apply a while loop logic it kinda prints only one page multiple times..
my code as goes::
<?php
set_time_limit(3600);
$i = 1;
$e = 839304-$i;
while(true){
require_once('dom/simple_html_dom.php');
$html =file_get_html('http://www.usmleforum.com/files/forum/2017/1/'.$e.'.php');
foreach ($html->find("tr") as $row) {
$element = $row->find('td.Text2',0);
if ($element == null) { continue; }
$textNode = array_filter($element->nodes, function ($n) {
return $n->nodetype == 3; //Text node type, like in jQuery
});
if (!empty($textNode)) {
$text = current($textNode);
echo $text."<br>";
}
}
$i++;
}
?>
as the result indicates, it only prints the statement from page 839303, but it prints it multiple times and still loads on.. so its clear that this code is skipping the $i++ line somehow and runs again...
Any help is appreciated...
Insert $e inside while loop will fix the problem. but it is an infine loop. so try to give an exit condition for while loop like: while($i < 100) or something else.
<?php
set_time_limit(3600);
$i = 0;
while($i < 10){
$e = 839303 + $i;
require_once('dom/simple_html_dom.php');
$html =file_get_html('http://www.usmleforum.com/files/forum/2017/1/'.$e.'.php');
foreach ($html->find("tr") as $row) {
$element = $row->find('td.Text2',0);
if ($element == null) { continue; }
$textNode = array_filter($element->nodes, function ($n) {
return $n->nodetype == 3; //Text node type, like in jQuery
});
if (!empty($textNode)) {
$text = current($textNode);
echo $text."<br>";
}
}
$i++;
}
?>
I'm new to PHP and programming in general so go easy with me!
I have a (drupal) mysql database and I want to select all url links from a data field and put them in a variable. There could be one link or many.
So this is what's in the database:
<ul>
<li><a href"link1.php">link1</a></li>
<li><a href"link2.php">link2</a></li>
</ul>
I need this in a variable. The variable will then be submitted via a hidden form field to an ASP page to display the data.
This is what I've tried so far:
<?php
global $base_url;
$iconPath = $base_url . "/sites/default/files/icons/";
if ( arg(0) == 'node' && is_numeric(arg(1)) && ! arg(2) ) {
$nodenew = node_load(arg(1));
//print node_load(arg(1));// returns a blank
}
$relatedPages2 = $nodenew->field_related_pages[0]['value'];
$pagesArray=explode('<a href="',$relatedPages2);
$howmanyItemsOnArray = count($pagesArray);
$start = 0;
$end = $howmanyItemsOnArray;
$split = 2;
$str = '';
$str.= "<ul>";
for($i = $start; $i < $end; $i++) {
$str.= "<li>".$clearPagesArray[$i]."</li>";
if(($i) % ($split) == $split-1){
}
}
$str.="</ul>";
//print($str);
//print relatedPages2;
?>
Any help would be much appreciated.
Hi replace the line like this,
$str = "<ul>";
for($i = $start; $i < $end; $i++) {
$str.= "<li><a href='".$pagesArray[$i]."'>".$clearPagesArray[$i]."</a></li>";
}
$str.="</ul>";
Hope this will work
I need to generate random number of divs with five items per div (and remaining items in the last div) from random number of $totalItems and also not all the items satisfy $OKItems... Hopefully the code explains better than me.
My problem is that this script generates empty divs with no content in them.
<?php
$OKItems = 0;
$totalItems = rand(2,30);
for ($i = 0; $i < $totalItems; $i++) {
echo ($OKItems == 0 || $OKItems % 5 == 0) ? 'div open<br />' : '';
$testValue = rand(0, 1);
if ($testValue != 0) {
echo '1';
$OKItems++;
}
echo ($OKItems % 5 == 0 || $i+1 == $totalItems) ? '<br />div close<br />' : '';
}
?>
This is what I might get:
div open
div close
div open
11111
div close
div open
div close
div open
div close
div open
11
div close
And this is what I would have wanted in this case:
div open
11111
div close
div open
11
div close
<?php
const N = 5;
$totalItems = rand(2,30);
$items = array() ;
for ($i = 0; $i < $totalItems; $i++) {
$testValue = rand(0, 1);
if ($testValue != 0) {
$items[] = 1 ;
}
if( N == sizeof($items) || (($i == $totalItems - 1) && 0 < sizeof($items)) ) {
echo "<div>" . join(",", $items) . "</div>";
$items = array() ;
}
}
I think you need a bit more structure to your code.
My approach would be to break it up into several stages, as opposed to trying to do all the logic in the loop that outputs data.
What I'd suggest:
Decide how many items to be tested
Test each item and only copy the ones that pass into a new array
Partition this new array into sets of 5
Output each partition as a div
Code (untested):
// Decide how many items to test
$totalItems = rand(2,30);
// Test these items and add them to an accepted array
$items = Array();
for ($i = 0; $i < $totalItems; $i++) {
$testValue = rand(0, 1);
if ($testValue != 0) { $items[] = "1" }
}
//Partition them into sections
$partitions = array_chunk($items,5);
//Output as divs
foreach($partitions as $partition):
echo 'div open <br />';
foreach($partition as $item):
echo $item . "<br />";
endforeach;
echo 'div close <br />';
endforeach;
When you split up the code into logical steps, it becomes much easier to maintain and debug.
<?php
$OKItems = 0;
$totalItems = rand(2,30);
for ($i = 0; $i < $totalItems; $i++) {
echo ($OKItems == 0 || $OKItems % 5 == 0) ? 'div open<br>' : '';
$testValue = rand(0, 1);
if ($testValue != 0) {
echo '1';
$OKItems++;
}
if($OKItems % 5 == 0 || $i+1 == $totalItems) {
echo '<br>div close<br>';
$OKItems = 0;
}
}
?>
That should be working ;)
I changed your check line for an if function that also resets your $OKItems. The problem you had (i think) was that you got a 0 as the random value and that would keep $OKitems on 5.