客戶把excel轉成html頁面,希望取裡面的table來使用
用file_get_contents取html的內容的話,會有一堆CSS跟JavaScript
所以我先使用preg_match取出我要的那個table
程式如下
$file = 'xxx.html';
$load = iconv('big5', 'utf-8', file_get_contents($file));
preg_match('/<table.*>.*<\/table>/is', $load, $arr);
$table = $arr[0];
但table裡面還會有一些奇怪的東西
像是<col width="76" style="width: 57pt;" class="xl65">
我想要清掉這些東西不知道該怎麼做
$table = preg_replace('/<col.*>/is', '', $table);
這樣是失敗的
perl 有非常好用的 HTML-Scrubber 的套件。
用實際例子示範:
擷取 這個xls 檔案轉成 slx.html測試:
<pre class="c" name="code">
<table border=0 cellpadding=0 cellspacing=0 width=209 style='border-collapse:
collapse;table-layout:fixed;width:157pt'>
<col width=54 style='mso-width-source:userset;mso-width-alt:1728;width:41pt'>
<col width=60 style='mso-width-source:userset;mso-width-alt:1920;width:45pt'>
<col width=95 style='mso-width-source:userset;mso-width-alt:3040;width:71pt'>
<tr class=xl65 height=22 style='height:16.5pt'>
<td height=22 class=xl66 width=54 style='height:16.5pt;width:41pt'>姓名</td>
<td class=xl67 width=60 style='width:45pt'>學號</td>
<td class=xl67 width=95 style='width:71pt'>身分證字號</td>
</tr>
<tr height=22 style='height:16.5pt'>
<td height=22 class=xl68 width=54 style='height:16.5pt;width:41pt'>溫志鴻<span
style='mso-spacerun:yes'> </span></td>
<td class=xl69 align=right width=60 style='width:45pt'>880001</td>
<td class=xl69 width=95 style='width:71pt'>J000000001</td>
</tr>
<tr height=22 style='height:16.5pt'>
<td height=22 class=xl68 width=54 style='height:16.5pt;width:41pt'>劉泓廷<span
style='mso-spacerun:yes'> </span></td>
<td class=xl69 align=right width=60 style='width:45pt'>880002</td>
<td class=xl69 width=95 style='width:71pt'>J000000002</td>
</tr>
<tr height=0 style='display:none'>
<td width=54 style='width:41pt'></td>
<td width=60 style='width:45pt'></td>
<td width=95 style='width:71pt'></td>
</tr>
<![endif]>
</table>
編個 簡單的 perl script 名叫 clean_html.l檔:
<pre class="c" name="code">#!/usr/bin/perl
open(F,$ARGV[0]);
@file = <F>;
close F;
use HTML::Scrubber;
foreach $line (@file) {
$html .= $line;
}
my $scrubber = HTML::Scrubber->new( allow => [ qw[ table tr td ] ] );;
my $clean_html = $scrubber->scrub($html);
print "$clean_html";
執行 perl clean_html.pl xls.html 跑出的結果變這樣:
<pre class="c" name="code"><table>
<tr>
<td>姓名</td>
<td>學號</td>
<td>身分證字號</td>
</tr>
<tr>
<td>溫志鴻 </td>
<td>880001</td>
<td>J000000001</td>
</tr>
<tr>
<td>劉泓廷 </td>
<td>880002</td>
<td>J000000002</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
程式碼若第10行若改為
$scrubber->default(0);
則是把所有 html 的標籤去掉。
所以那第十行的 allow 可定你要留的標籤。
也可參考使用範例 Strip/sanitize HTML with Perl
這個 HTML::Scrubber 在linux很容易裝,
在 Fedora/RedHat/CentOS 類,
yum install perl-HTML-Scrubber
在 Ubuntu 類:
aptitude install libhtml-scrubber-perl
就裝起來了。
若有大量檔案轉,就可先用這簡單的 script 幫你保留只要的標籤,
然後再用你熟悉的程式來處理這些檔案。
twtw提到:
程式碼若第10行若改為
應是第11行。
那個 clean_html.pl 檔簡化成這樣就可以了:
<pre class="c" name="code">#!/usr/bin/perl
use HTML::Scrubber;
my $scrubber = HTML::Scrubber->new( allow => [ qw[ table tr td ] ] );
my $clean_html = $scrubber->scrub_file($ARGV[0]);
print "$clean_html";
我是問PHP說 =3=
如果要純php的話,就得試試 Pear的HTML_Safe
在回答的補充說明裡的一個討論連結,有人提這可做到 perl 的 HTML::Scrubber 的功能。
php 的強項在於做網頁程式互動的處理,
至於這種解析較麻煩的資料,不必拘泥在只能用php,
perl 提供的解決方案,相較之下是更簡單讓你達到目的。
可以用php的exec 來執行這外部的 perl script。
可能類似這樣的寫法,就得到上述範例的乾淨table了:
<pre class="c" name="code">
$table = exec('perl clean_html.pl $file');
就省掉了很多用 php 的 regular expression 從造輪子開始的辛苦。
如果您不方便在linux平臺操作的話,
可裝 windows 版的 perl。
只要下載安裝 這個安裝檔,
然後後執行
<pre class="c" name="code">ppm install HTML::Scrubber
就可把該套件裝上。
雖然順利將table取進來,可是Excel產生的html製造出許多廢tr(2000多個)
所以在client使用js重組表格時遇到了效能上的問題
希望詢問某些內容是否可以在Server端使用正規式做掉
如果有些具體的少許實例,不涉及貴單位敏感內容,
比較容易推想可能的處理方向。
就1.而言,如果 <tr><td>xxx</td></tr>這麼單純形式的話,
regex就很容易處理。
但實際可能是 tr, td, xxx 都錯開而沒在同一行;
這時就可能需要看看能不能用 tidy 整理整齊後,
方便 regex 處理。
或者,要有像 jQuery 可以 parse HTML 的工具,
在 ruby 像 Hpricot、
在 perl 裡一些的 Parsing HTML的模組,
或者以 DOM 的角度去處理,會比單靠 regex 處理來得有效。
php 的 PHP Simple HTML DOM Parser 也許可以符合你在 Server 端處理的要求。
就2.而言,
檔案複製出來,自行邊砍邊測試。
如果所有的檔案的行數都一致、
格式一致,只有關鍵數值不同的話,
就更容易以「行」為單位來處理。
Excel?幹麼不轉成CSV格式咧...這樣就不用跟微軟自訂的一堆html tag打交道了。
我正在跟他們打交道…
客戶流程沒辦法改變,只能從中想辦法
有熱心的網友提供變通的方式
用strip_tags($str, '<table><tr><td><img>')
這樣已經滿足我第一階段的需求
接著要用正規化清除所有的style跟找出該字串所有符合img的標籤
正規表示式~每次寫完以後每次都馬上把他丟掉XD~
每次寫的時候又要重新看ㄧ次XD
跟我一樣 XD
這樣喔...
那你用tidy看看,裡面有簡單的範例。不過<col />是合法的html tag,tidy不會幫你清掉。通常要配合一下設定,用陣列傳給parseString方法,可以用的設定可以參考http://tidy.sourceforge.net/docs/quickref.html
通常預設是不會開啟tidy的,請在php.ini打開他。另外,可以用show-body-only選項讓他只顯示body tag之內的內容,減少後續處理的麻煩。例如:
<pre class="c" name="code">
<?php
$html = 'html內容字串';
$config = array(
'bare' => true,
'show-body-only' => true,
'indent' => true,
'output-html' => true,
'wrap' => 200);
$tidy = new tidy;
$tidy->parseString($html, $config, 'utf8');
$tidy->cleanRepair();
echo $tidy;
?>
(拿範例稍微改一下)
阿,如果你不要<col />標籤,你還得自己想辦法parse掉。