在 PHP 中删除表上的行跨度
Posted
技术标签:
【中文标题】在 PHP 中删除表上的行跨度【英文标题】:Remove rowspan on tables in PHP 【发布时间】:2012-11-30 07:59:11 【问题描述】:我想将这张表加载到多维数组中。问题在于,由于表格具有行跨度值,因此每行可能具有不同的单元格计数。所以我必须删除行跨度并添加空值而不是这些单元格。
这是我的表(原始文件)(大约有 5k 行。)
我必须像这样添加这个表才能有一个正确的数组。
删除第一行的 colspan 值很容易。但是在当前方法中删除行跨度有时会导致数组中出现额外的值。
我当前的 php 文件:
<?php
ini_set('display_errors', true);
ini_set('mbstring.internal_encoding','UTF-8');
ini_set("memory_limit", "1024M");
ini_set('max_execution_time', 300);
include('simple_html_dom.php');
// Create a DOM object
$html = new simple_html_dom();
$html->load_file('stok.html');
$table = array();
$kac = array();
foreach($html->find('tr') as $row)
$satir = array();
$j = 0;
foreach($row->find('td') as $element)
if($kac[$j]['deger']>0)
$satir[]='';
$kac[$j]['deger']=$kac[$j]['deger']-1;
$j++;
while($kac[$j]['deger']>0)
$satir[]='';
$kac[$j]['deger']=$kac[$j]['deger']-1;
$j++;
else
$j++;
if(isset($element->rowspan))
$kac[$j]['deger']=($element->rowspan)-1;
$satir[] = str_replace(' ', '', strip_tags($element->innertext));
if(isset($element->colspan))
$sayi=($element->colspan)-1;
for($i=1;$i<=$sayi;$i++)
$satir[] = '';
$table[] = $satir;
echo '<pre>';
print_r($table);
echo '</pre>';
?>
我当前的输出示例:(请参阅某些数组值中有 21、23 和 17 项。正确的是 21 项。(20 作为索引值))--没有删除示例输出中的表值--
Array
(
[0] => Array
(
)
[1] => Array
(
[0] => Envanter (R/B/K) (Filitre Kodu : sa) (Envanter Tarihi :28/11/2012 ) (Depo : 100)
[1] =>
[2] =>
[3] =>
[4] =>
[5] =>
[6] =>
[7] =>
[8] =>
[9] =>
[10] =>
[11] =>
[12] =>
[13] =>
[14] =>
[15] =>
[16] =>
[17] =>
[18] =>
[19] =>
[20] =>
)
[2] => Array
(
[0] => Model
[1] => Stok Adı
[2] => R
[3] => Renk Adı
[4] => B
[5] => B
[6] => B
[7] => B
[8] => B
[9] => B
[10] => B
[11] => B
[12] => B
[13] => B
[14] => B
[15] => B
[16] => B
[17] => B
[18] => B
[19] => Toplam
[20] => Resim
)
[3] => Array
(
[0] =>
[1] =>
[2] =>
[3] =>
[4] => 34
[5] => 36
[6] => 38
[7] => 40
[8] => 42
[9] => 44
[10] => 46
[11] => 48
[12] => 50
[13] => 52
[14] => 54
[15] => 56
[16] => 58
[17] => 60
[18] => 62
[19] => Toplam
[20] =>
)
[4] => Array
(
[0] => 1K011621110
[1] => NIHAN 2111 KABAN
[2] => 064
[3] => FES
[4] =>
[5] =>
[6] =>
[7] =>
[8] =>
[9] =>
[10] =>
[11] =>
[12] => 1.00
[13] =>
[14] =>
[15] =>
[16] =>
[17] =>
[18] =>
[19] => 1.00
[20] => Resim
)
[5] => Array
(
[0] =>
[1] =>
[2] => Toplam :
[3] =>
[4] =>
[5] =>
[6] =>
[7] =>
[8] =>
[9] =>
[10] =>
[11] =>
[12] =>
[13] =>
[14] =>
[15] => 1.00
[16] =>
[17] =>
[18] =>
[19] =>
[20] =>
[21] =>
[22] => 1.00
[23] =>
)
[6] => Array
(
[0] =>
[1] => 34
[2] => 36
[3] => 38
[4] => 40
[5] => 42
[6] => 44
[7] => 46
[8] => 48
[9] => 50
[10] => 52
[11] => 54
[12] => 56
[13] => 58
[14] => 60
[15] => 62
[16] => Toplam
[17] =>
)
[7] => Array
(
[0] => 1K011624760
[1] => NIHAN 2476 KABAN
[2] => 001
[3] => SIYAH
[4] =>
[5] =>
[6] =>
[7] =>
[8] =>
[9] => 1.00
[10] =>
[11] => 1.00
[12] =>
[13] =>
[14] =>
[15] =>
[16] =>
[17] =>
[18] =>
[19] => 2.00
[20] => Resim
)
提前致谢。
使用工作代码更新解决方案:目前用“***”填充所有空单元格
<?php
ini_set('display_errors', true);
ini_set('mbstring.internal_encoding','UTF-8');
ini_set("memory_limit", "1024M");
ini_set('max_execution_time', 300);
include('simple_html_dom.php');
// Create a DOM object
$html = new simple_html_dom();
$html->load_file('stok.html');
$satir = array();
$rowcount = 0;
foreach($html->find('tr') as $row)
$colcount = 0;
foreach($row->find('td') as $element)
while($satir[$rowcount][$colcount]!='')
$colcount++;
$satir[$rowcount][$colcount] = strip_tags(str_replace(' ', '***', $element->innertext));
if(isset($element->colspan))
$sayi=($element->colspan)-1;
for($i=1;$i<=$sayi;$i++)
$satir[$rowcount][$colcount+$i] = '***';
if(isset($element->rowspan))
$sayi=($element->rowspan)-1;
for($i=1;$i<=$sayi;$i++)
$satir[$rowcount+$i][$colcount] = '***';
$colcount++;
$rowcount++;
echo '<pre>';
print_r($satir);
echo '</pre>';
?>
【问题讨论】:
这很棘手。删除行跨度已经需要您进行一些复杂的计算来填补剩余的空洞。我会跳过这一步并使用相同类型的计算直接填充结果数组。即,完全初始化所有维度的结果数组,然后逐行遍历表格;当遇到row/colspan时,可以用相同的值预先填充数组的相关维度... 由于值必须按探测器顺序排列,我无法直接填充数组。正如你所说,我要做的是删除行跨度并在正确的位置添加空单元格值,直到行跨度结束。 是的,您可以直接填充它,即使顺序正确。当您遍历表时,您会跟踪您所在的$x
和 $y
索引。例如,当您遇到行跨度为 2 时,您将 $result[$x][$y]
和 $result[$x + 1][$y]
设置为当前单元格的值。当您到达$x + 1,$y
时,数组条目已被填充,这有助于您在填充数组时跟踪行跨度。这只是我的想法,但它似乎是一种合理的方法。
是的,听起来很合理,但有一些复杂性。我将根据您的想法编辑我的代码并分享结果。
请做。如果我有时间,我也会尝试一下...... :)
【参考方案1】:
根据@deceze 的有用评论,我使用了不同的方法来解决问题。下面的代码将完成这项工作。但它会用***
填充所有空白字段。之后您可能需要重新访问整个数组以清空它。 (此代码位于下方)
// Create a DOM object
$html = new simple_html_dom();
$html->load_file('stok.html');
$satir = array();
$rowcount = 0;
foreach($html->find('tr') as $row)
$colcount = 0;
foreach($row->find('td') as $element)
while($satir[$rowcount][$colcount]!='')
$colcount++;
$satir[$rowcount][$colcount] = strip_tags(str_replace(' ', '***', $element->innertext));
if(isset($element->colspan))
$sayi=($element->colspan)-1;
for($i=1;$i<=$sayi;$i++)
$satir[$rowcount][$colcount+$i] = '***';
if(isset($element->rowspan))
$sayi=($element->rowspan)-1;
for($i=1;$i<=$sayi;$i++)
$satir[$rowcount+$i][$colcount] = '***';
$colcount++;
$rowcount++;
echo '<pre>';
print_r($satir);
echo '</pre>';
?>
下面的代码块将从我上面提到的那些星号中清除数组。
$itemcount=count($satir)-1;
for($i=1; $i<=$itemcount; $i++)
for($j=0; $j<=20; $j++)
if($satir[$i][$j]=='***')
$satir[$i][$j]='';
【讨论】:
【参考方案2】:也许这在最近的时间里会更有帮助。我们可以使用各种工具来帮助我们删除合并的行和/或列,如下所示:
<?
namespace app;
use PhpOffice\PhpSpreadsheet\ExcelFactory;
class table
private function removeMergedCells(\DOMDocument $dom): \DOMDocument
$xpath = new \DOMXPath($dom);
$search = $xpath->query('//table');
/** @var \DOMNode $node */
foreach ($search as $node)
$html = $dom->saveXML($node);
$tmpHtml = \tempnam(\sys_get_temp_dir(), 'html');
$tmpTable = \tempnam(\sys_get_temp_dir(), 'table');
\file_put_contents($tmpHtml, $html);
$table = ExcelFactory::load($tmpHtml);
$merged = ($table->getAllSheets())[0]->getMergeCells();
foreach ($merged as $cell)
$table->getActiveSheet()->unmergeCells($cell);
// this $writerType is case sensitive
$writer = ExcelFactory::createWriter($table, 'Html');
$writer->save($tmpTable);
$domNew = new \DOMDocument();
$domNew->loadHTML(\file_get_contents($tmpTable));
$nodeNew = $dom->importNode($domNew->getElementsByTagName('body')[0], true);
$node->parentNode->replaceChild($nodeNew, $node);
return $dom;
?>
【讨论】:
以上是关于在 PHP 中删除表上的行跨度的主要内容,如果未能解决你的问题,请参考以下文章