How to use simple html DOM for this table? - php

hi everybody i want to dom a webpage and fetch data from it's table.
table code :
<tbody>
<tr class="sh" onclick="ii.ShowShareHolder('21711,IRO1DMOR0004')">
<td>person</td>
<td><div class="ltr" title="1,100,000">1 M</div></td>
<td>2.050</td>
<td>0</td>
<td><div class=""></div></td>
</tr>
<tr class="sh" onclick="ii.ShowShareHolder('42123,IRO1DMOR0004')">
<td>person</td>
<td>953,169</td>
<td>1.780</td>
<td>0</td>
<td><div class=""></div></td>
</tr>
</tbody>
this table has two kind of data bigger than 1M and smaller than 1M . i want to get the 1.100.000 td div data and 953.169 data on this table.
my code is below.it works fine for bigger than 1M data but i don't know how to get the smaller data on this table.
foreach ($tables as $table) {
foreach ($table->find('tr') as $row) {
foreach($row->find('div') as $div)
{
if(array_key_exists('title',$div->attr))
{
$data[] = str_replace(",","",($div->attr['title']));
}
}
}
}

tnx man i use your code but it doesn't work and have many error.
this is my complete functions code.because the server is gzip encode i read with curl .
$url = "http://tsetmc.com/Loader.aspx?Partree=15131T&c=IRO1DMOR0004";
$curl = curl_get_data($url);
if(!empty($curl) ){
$html = str_get_html($curl);
$xml = simplexml_load_string($html);
var_dump($xml);
$data = [];
// For each <tr>
foreach ($xml->tr as $row) {
// check path `<td><div title="">`
$result = $row->xpath('td/div[#title]');
if (! empty($result)) {
foreach ($result as $item) {
$data[] = str_replace(',', '', $item['title']);
}
}
else {
// if not found, check the 2nd <td>
$result = $row->xpath('td[position()=2]');
foreach ($result as $item) {
$data[] = str_replace(',', '', $item);
}
}
}
return $data;
}

You could check if the <div title=""> exist. If true, get that value, else, get the value of the second <td>.
Here is an example using SimpleXML:
$html = <<<HTML
<tbody>
<tr class="sh" onclick="ii.ShowShareHolder('21711,IRO1DMOR0004')">
<td>person</td>
<td><div class="ltr" title="1,100,000">1 M</div></td>
<td>2.050</td>
<td>0</td>
<td><div class=""></div></td>
</tr>
<tr class="sh" onclick="ii.ShowShareHolder('42123,IRO1DMOR0004')">
<td>person</td>
<td>953,169</td>
<td>1.780</td>
<td>0</td>
<td><div class=""></div></td>
</tr>
</tbody>
HTML;
// parse HTML
$xml = simplexml_load_string($html);
$data = [];
// For each <tr>
foreach ($xml->tr as $row) {
// if not found, check the 2nd <td>
$item = $row->children()[1];
// check if a div with title exists
if (isset($item->div['title'])) {
$data[] = str_replace(',', '', $item->div['title']);
}
else { // else, take the content
$data[] = str_replace(',', '', $item);
}
}
var_dump($data);
Output:
array(2) {
[0]=>
string(7) "1100000"
[1]=>
string(6) "953169"
}
See the live demo.

Related

sorting PHP array by element in a foreach loop

I use PHP to access some data which is contained in a text file.
Here is a sample of the text file (myfile.txt) - each line has three fields separated by ||:
4e84||some text||category A
f17b||words words||category B
f7ac||some more text here||category B
8683||text text||category C
b010||more text||category A
fcc4||more text||category B
we47||more text||category C
08ml||more text||category A
This is the PHP code I use to show the contents of the txt file in a simple HTML table.
I access the file and I loop through each line to extract the three parts:
<?php
$lines = file("myfile.txt");
?>
<table>
<thead>
<tr>
<th>ID</th>
<th>TEXT</th>
<th>CATEGORY</th>
</tr>
</thead>
<tbody>
<?php
foreach ($lines as $line) {
list($id,$text,$category) = explode('||', $line);
echo '<tr>';
echo '<td>'.$id.'</td>';
echo '<td>'.$text.'</td>';
echo '<td>'.$category.'</td>';
echo '</tr>';
}
?>
</tbody>
</table>
I need to sort the lines according to the third field (category), so as to show the entries of category A, then B and then C.
I tried to use the sort() command within the foreach loop, with no success.
Any ideas?
You can use next approach:
$split_lines = [];
// first - split lines and put them into array
foreach ($lines as $line) {
$split_lines[] = explode('||', $line);
}
// sort array by function
usort($split_lines, fn($a,$b)=>$a[2]<=>$b[2]);
// show array as table
foreach ($split_lines as $line) {
echo '<tr>';
echo '<td>'.$line[0].'</td>';
echo '<td>'.$line[1].'</td>';
echo '<td>'.$line[2].'</td>';
echo '</tr>' . PHP_EOL;
}
run PHP online
You can achive it using two for loop only.
<?php
$lines = file("myfile.txt");
?>
<table>
<thead>
<tr>
<th>ID</th>
<th>TEXT</th>
<th>CATEGORY</th>
</tr>
</thead>
<tbody>
<?php
$listOfFiles = array();
foreach ($lines as $line) {
list($id,$text,$category) = explode('||', $line);
array_push($listOfFiles,$category."||".$text."||".$id);
}
sort($listOfFiles);
foreach($listOfFiles as $line)
{
list($category,$text,$id) = explode('||', $line);
echo '<tr>';
echo '<td>'.$id.'</td>';
echo '<td>'.$text.'</td>';
echo '<td>'.$category.'</td>';
echo '</tr>';
}
?>
</tbody>
</table>

condition checking inside the foreach loop and printing multiple result with in one row

I have an array of result after searching parameters,i want to print that result.while printing the result using foreach loop,i need to check the condition that ,if purchase dates are same, they should be printed in same row.How i can implement this?please help me.Thanks in advance
here is my code: ( i have get the result in controller and then i append the result in view)
foreach($res as $key => $row)
{
$i++;
$billfirst='';
$billend= $row['bill_date'];
if( $billfirst != $billend){
echo "<tr>
<td class='txt'> ".$i."</td>
<td class='txt'> ".$row['store']."</td>
<td class='txt'> ".$row['cust']."</td>
<td class='txt'> ".$row['name']."</td>
<td class='txt'> ".$row['net_amount']."</td>
<td class='txt'> ".$row['bill_date']."</td>
</tr>" ;
}
else {
echo "<tr><td class='txt'> ".$row['name']."</td>
<td class='txt'> ".$row['net_amount']."</td>
<td class='txt'> ".$row['bill_date']."</td>
</tr>";
}
$billfirst == $billend;
echo "</tbody></table>";
}
You need to make additional array to group your rows, example:
$arRows = array();
$billPrevious = "empty";
// save new grouped array
foreach($res as $key => $row) {
$arRows[$row['bill_date']][] = $row;
}
// show groups - in the way you want to group it visually in table
foreach ($arRows as $key => $arGroup) {
echo '<tr>';
$arName = '';
$arStore = '';
foreach ($arGroup as $keyInGroup => $row) {
$arName[] = $row['name'];
$arStore[] = $row['store'];
}
echo '<td>'.implode('<br>', $arName).'</td>';
echo '<td>'.implode('<br>', $arStore).'</td>';
echo '</tr>';
}

Parsing content with Simple html dom from a table but with a condition

So I want to show in an 'echo' only the people that day which the situation is 'Yes', so let's assume today is only 'John' from my array list that have the situation 'Yes'.
$people = array('John', 'Greg', 'Mike', 'James', 'Jason');
$situation = array('Yes');
$html = str_get_html('<table class="mytab">
<tr>
<th>Name</th>
<th>Situation</th>
</tr>
<tr>
<td>
John
</td>
<td class="s">
<strong>Yes</strong>
</td>
</tr>
<tr>
<td>
Allan
</td>
<td class="s">
<strong>No</strong>
</td>
</tr>
<tr>
<td>
James
</td>
<td class="s">
<strong>No</strong>
</td>
</tr>
</table>');
$table = $html->find('table', 0);
$rowData = array();
foreach($table->find('tr') as $row) {
// initialize array to store the cell data from each row
$content= array();
foreach($row->find('td') as $cell) {
// push the cell's text to the array
$content[] = $cell->plaintext;
}
$rowData[] = $content;
}
echo '<table>';
foreach ($rowData as $row => $tr) {
echo '<tr>';
foreach ($tr as $td)
echo '<td>' . $td .'</td>';
echo '</tr>';
}
echo '</table>';
The code above is going to show:
John Yes
Allan No
James No
It's driving me insane I can't figure it out!!
How can I search in the <td>s and get only the people 'Yes' that day?
Assuming your $html is a valid XML string (meaning each tag closes properly, and has a parent tag, and no text outside tags), do this:
$html="<table>..";
$xml = new SimpleXmlElement($html);
$result=array();
foreach($xml->tr as $tr){
//you have your td, see what it has
$name='';
foreach($tr->td as $td) {
if(isset($td->a))
$name=$td->a;
if(isset($td->strong) && $td->strong=='Yes'){
$result[]=strval($name);
}
}
}
print_r($result); //this will have array with name of those where YES
Array
(
[0] => John
)
EDIT: , if you have a well-known XML format of the html, no need to go and check every td. Here I remove nested loop, and reducing complexity from O(n2) to O(n).
$result=array();
foreach($xml->tr as $tr){
//just in case see if a tag is there
if(isset($tr->td[0]->a))
$name = $tr->td[0]->a;
$td2 = $tr->td[1];
if(isset($td2->strong) && $td2->strong=='Yes'){
$result[]=strval($name);
}
}
print_r($result);

Simple html dom parser - two rows in one

I trying to insert a table in database, and I want to convert two rows in one array.
Can anyone help me out?
<table>
<tr class="pair"><td>1</td><td>2</td></tr>
<tr class="pair">td<>3</td><td>4</td></tr>
<tr class="unpair"><td>1</td><>2</td></tr>
<tr class="unpair"><td>3</td><td>4</td></tr>
</table>
<?php
require('simple_html_dom.php');
foreach($table->find('tr[class=pair') as $rowpair) {
$rowData = array();
foreach($rowpair->find('td') as $cell) {
$rowData[] = $cell->innertext;
}
foreach($table->find('tr[class=unpair') as $rowunpair) {
$rowData = array();
foreach($rowunpair->find('td') as $cell) {
$rowData[] = $cell->innertext;
}
?>
to obtain
<table>
<tr class="pair"><td>1</td><td>2</td><td>3</td><td>4</td></tr>
<tr class="unpair"><td>1</td><td>2</td><td>3</td><td>4</td></tr>
</table>
This should work to group all table rows by class.
The basic logic is to loop through all the rows in a table and identify if it's seen that class before or not. If it hasn't, it'll store reference to that row as the 'canonical' row to use. If it has seen the class before, it will transfer over all it's children to the canonical row.
This approach should work for any number of tables in a blog and any set of class names.
<?php
$str = '<table><tr class="pair"><td>1</td><td>2</td></tr><tr class="pair"><td>3</td><td>4</td></tr><tr class="unpair"><td>1</td><td>2</td></tr><tr class="unpair"><td>3</td><td>4</td></tr>
</table>';
$doc = new DOMDocument();
$doc->loadHTML($str);
$tables = $doc->getElementsByTagName('table');
foreach ($tables as $table) {
#For each TR in the table, group into rows
$table_classes = array();
$rows = $table->getElementsByTagName('tr');
$row_list = array();
foreach ($rows as $row) {
array_push($row_list, $row);
}
for($i=0; $i<count($row_list); $i++){
$row = $row_list[$i];
$row_class = $row->getAttribute('class');
if(!array_key_exists($row_class, $table_classes)){
#if this is the for occurrence of that clase, store this row as the original_row
$table_classes[$row_class] = $row;
}else{
$original_row = $table_classes[$row_class];
#Move children over to original row
foreach ($row->childNodes as $child) {
$clone = $child->cloneNode(true);
$original_row->appendChild($clone);
}
#Now delete original
$row->parentNode->removeChild($row);
}
}
}
echo htmlspecialchars($doc->saveXML());
?>
Returns:
<table>
<tr class="pair">
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr class="unpair">
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</table>

xpath match not working

I'm trying to fetch the content of message field with "//td[text()='message']/following-sibling::*/text()" from this result ( from curl ):
<BODY bgcolor=#dddddd>
<TABLE bgcolor=#dddddd border=1>
<TR>
<TD valign="top"><B>Something</B></TD>
<TD>ca</TD>
</TR>
<TR>
<TD valign="top"><B>Some list</B></TD>
<TD>
<TABLE>
<TR>
<TD>CA</TD>
</TR>
</TABLE>
</TD>
</TR>
<TR>
<TD valign="top"><B>message</B></TD>
<TD>CA already existed.</TD>
</TR>
</TABLE>
</BODY>
<br>
But it doenst seens to work, The funny thing is using the same expression with python i can get it to work. So, how could i get the content of the message field?
PS: I'm using this online tester tool: http://www.xpathtester.com/test
EDIT: This is my actual php code:
<?php
function get_url_data($acl)
{
// curl request
$xml_content = http_request($acl);
echo $xml_content ;
$dom = new DOMDocument();
#$dom->loadXML($xml_content);
$xpath = new DomXPath($dom);
$content_title = $xpath->query("//td[text()='message']/following-sibling::*/text()");
return $content_title;
}
if(isset($_POST)==true && empty($_POST)==false){
//Convert content of text area into an array
$data = explode("\n", str_replace("\r", "", $_POST['sendme']));
}
foreach ($data as $name => $value){
$content = get_url_data($value);
foreach ($content as $value)
{
echo $value->nodeValue . "<br/>";
}
echo "<br>";
}
?>
I was able to get it working with:
<?php
if(isset($_POST)==true && empty($_POST)==false){
//Convert content of text area into an array
$data = explode("\n", str_replace("\r", "", $_POST['sendme']));
}
foreach ($data as $name => $value){
$content = create_acl($value);
$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
#$doc->loadHTML($content);
$xpath = new DOMXpath($doc);
$filtered = $xpath->query("//td[text()='message']/following-sibling::*/text()");
foreach ($filtered as $e) {
echo $e->nodeValue;
}
echo "<br>";
}
?>

Categories