Napisałem prosty mechanizm do konwersji danych tabelerycznych. Proszę o ocenę.
Wszelkie uwagi pożądane. Z góry dziękuję.
CODE
abstract class Table implements ITable{
protected $table_input;
protected $data_to_print;
public $attributes;
protected $dom;
private $class;
private $metod;
public function __construct() {
$this->dom=new DOMDocument();
$this->class=get_class($this);
$this->data_to_print=array_key_exists('table',$this->toArray())?$this->toArray()['table']:$this->toArray();
$this->attributes=array_key_exists('attributes',$this->toArray())?$this->toArray()['attributes']:null;
}
public function __call($method, $args){
if(method_exists($this, $method)){
$this->metod=$method;
$method_name=explode('_',$method);
if($this->class!=end($method_name)){
return call_user_func_array(array($this, $method), $args);
}else{
throw new Exception("You can't call this method for this class, you already have this data");
}
}
}
protected function draw_HTMLList($file=null){
$body= $this->data_to_print;
ob_start();
$out=array();
$index=1;
for($i=0;$i<$index;$i++){
$new=array();
foreach($body as $rows=>$row){
foreach ($row as $ix=>$cell){
$index= count($cell);
$new[]=$cell[$i];
}
}
$out[]=$new;
}
ob_start();
echo '<ul>';
foreach ($out as $list){
echo '<li>';
foreach ($list as $key=>$val){
if($key==0){
echo $val.'<ul>';
}else{
echo '<li>'.$val.'</li>';
}
}
echo '</ul></li>';
}
echo '</ul>';
$output= ob_get_clean();
ob_end_clean();
if($file!=null){
$this->filePutContent($file, $output);
}else {
return $output;
}
}
protected function drawDom_HTMLLList(){
$body= $this->data_to_print;
ob_start();
$out=array();
$index=1;
for($i=0;$i<$index;$i++){
$new=array();
foreach($body as $rows=>$row){
foreach ($row as $ix=>$cell){
$index= count($cell);
$new[]=$cell[$i];
}
}
$out[]=$new;
}
$ul_list= $this->dom->createElement('ul');
foreach ($out as $list){
$item= $this->dom->createElement('li');
foreach ($list as $key=>$val){
if($key==0){
$paragraf= $this->dom->createElement('p');
$paragraf->appendChild($this->dom->appendChild($this->dom->createTextNode($val)));
$item->appendChild($paragraf);
$sub_list=$this->dom->createElement('ul');
}else{
$item->appendChild($sub_list);
$sub_list_item=$this->dom->createElement('li');
$sub_list_item->appendChild($this->dom->createTextNode($val));
$sub_list->appendChild($sub_list_item);
}
}
$ul_list->appendChild($item);
}
return $ul_list;
}
protected function drawDom_HTMLTable(){
$body= $this->data_to_print;
$table= $this->dom->createElement('table');
$table->setAttribute('border','1');
foreach($body as $rows){
$row= $this->dom->createElement('tr');
for($i=0;$i<count(current($rows));$i++){
if(array_key_exists('th',$rows)){
$tab_head= $this->dom->createElement('th');
$tab_head->appendChild($this->dom->createTextNode($rows['th'][$i]));
$row->appendChild($tab_head);
}elseif (array_key_exists('td',$rows)) {
$tab_data= $this->dom->createElement('td');
$tab_data->appendChild($this->dom->createTextNode($rows['td'][$i]));
$row->appendChild($tab_data);
}
}
$table->appendChild($row);
}
return $table;
}
protected function draw_HTMLTable($file=null){
$body= $this->data_to_print;
ob_start();
echo '<table border="1">';
foreach($body as $rows){
echo '<tr>';
for($i=0;$i<count(current($rows));$i++){
if(array_key_exists('th',$rows)){
echo '<th>';
echo $rows['th'][$i];
echo '</th>';
}elseif (array_key_exists('td',$rows)) {
echo '<td>';
echo $rows['td'][$i];
echo '</td>';
}
}
echo '</tr>';
}
echo '</table>';
$output= ob_get_contents();
ob_end_clean();
if($file!=null){
$this->filePutContent($file, $output);
}else {
return $output;
}
}
protected function draw_XMLTable($file=null){
$body= $this->data_to_print;
$header=array();
$output='<?xml version="1.0" encoding="UTF-8"?><tabela>';
$header= array_shift ($body);
$header=$header['th'];
foreach($body as $rows=>$row){
$output.='<row>';
for($i=0;$i<count(current($row));$i++){
$output.= '<'.$header[$i].'>';
$output.= $row['td'][$i];
$output.= '</'.$header[$i].'>';
}
$output.= '</row>';
}
$output.= '</tabela>';
if($file!=null){
$this->filePutContent($file, $output);
}else {
return htmlentities($output);
}
}
protected function draw_JSONTable($file=null){
if($file!=null){
if($this->attributes){
$this->filePutContent($file,json_encode(array('table'=>$this->data_to_print,'attributes'=> $this->attributes),JSON_FORCE_OBJECT));
}else{
$this->filePutContent($file,json_encode(array('table'=>$this->data_to_print),JSON_FORCE_OBJECT));
}
}else{
return $this->attributes?json_encode(array('table'=>$this->data_to_print,'attributes'=> $this->attributes),JSON_FORCE_OBJECT):json_encode(array('table'=>$this->data_to_print),JSON_FORCE_OBJECT);
}
}
/**
* Save csv in $file
* @param type $file path to file
*/
protected function draw_CSVTable($file){
$body= $this->data_to_print;
foreach ($body as $lines){
foreach ($lines as $line){
$new_line[]=implode(';',$line).PHP_EOL;
$this->filePutContent($file, $new_line);
}
}
}
/**
* Draw ascii table or put into $file
* @param type $file
* @return type
*/
protected function draw_ASCITable($file=null){
$body= $this->data_to_print;
$out=array();
$index=1;
for($i=0;$i<$index;$i++){
$new=array();
foreach($body as $rows=>$row){
foreach ($row as $cell){
$index= count($cell);
$new[]=$cell[$i];
}
}
$str_lengths[]=max(array_map('strlen', $new));
$row_separator[$i] = str_repeat('-', $str_lengths[$i]);
$col_separator[$i] ="%-{$str_lengths[$i]}s";
$out[]=$new;
}
$row_separator='+-'.implode('-+-',$row_separator).'-+';
$col_separator='| '. implode(' | ', $col_separator) .' |';
foreach($body as $rows=>$row){
foreach ($row as $cell){
$bufor[]=$row_separator;
$bufor[]= vsprintf($col_separator, $cell);
}
}
$bufor[]=$row_separator;
ob_start();
echo '<pre>';
echo implode("\n", $bufor);
echo '</pre>';
$ret_str= ob_get_contents();
ob_end_clean();
if($file!=null){
$this->filePutContent($file, implode("\n", $bufor));
}else {
return $ret_str;
}
}
/**
*
* @param type $file
* @param type $output
* @throws Exception
*/
private function filePutContent($file,$output){
if(file_exists($file)){
if(is_writable($file)){
file_put_contents($file, $output);
}else{
throw new Exception('File '.$file.' is not writeable');
}
}else{
throw new Exception('File '.$file.' not exist');
}
}
}
I reszta, parser HTML
CODE
class HTMLTable extends Table implements ITable{
public function __construct($doc,$table_id=null) {
$this->dom=new DOMDocument();
$this->dom->preserveWhiteSpace = false;
$this->table_input=$this->getTableData($doc,$table_id);
parent::__construct();
}
public function getTableData($doc,$table_id=null){
$ext=array('html','phtml');
if(file_exists($doc)){
if(in_array(strtolower(pathinfo($doc,PATHINFO_EXTENSION)),$ext)){
$this->dom->loadHTMLFile($doc);
}else{
throw new Exception("File type ".pathinfo($doc,PATHINFO_EXTENSION)." does not match expected ".implode(',', $ext)."");
}
}else{
if(!(strcmp( $doc, strip_tags($doc) ) == 0))
$this->dom->loadHTML($doc);
}
if($this->dom->getElementById($table_id)!=null){
$table=$this->dom->getElementById($table_id);
}elseif ($this->dom->getElementsByTagName('table')->item(0)!=null) {
$table=$this->dom->getElementsByTagName('table')->item(0);
}else {
die('cos nie tak');
throw new Exception('nie ma tablei');
}
return $table;
}
public function toArray(){
$result = array();
$arrt = array();
if($this->hasAttribute($this->table_input))
$attr[$this->table_input->tagName]=$this->hasAttribute($this->table_input);
foreach($this->table_input->childNodes as $key=>$row){
if(strtolower($row->nodeName) != 'tr') continue;
if($this->hasAttribute($row))
$attr[$row->tagName][$key]=$this->hasAttribute($row);
$rowdata = array();
foreach($row->childNodes as $i=>$cell){
if((strtolower($cell->nodeName) != 'td')&&(strtolower($cell->nodeName) != 'th')) continue;
$rowdata[$cell->nodeName][] = $cell->textContent;
}
$result[] = $rowdata;
}
return array('table'=>$result,'attributes'=>$attr);
}
public function hasAttribute(DOMElement $element){
$attributes=array();
foreach ($element->attributes as $attr){
if($attr->value){
$attributes[$attr->name]=$attr->value;
}
}
if(!empty($attributes))
return $attributes;
return false;
}
public function __destruct() {
$this->dom->saveHTML();
}
}
interface ITable { /** * parse data to array * * * array[table][] * [th]=> array of header cells * [td]=> 1:n array of data cells * * @return array with parse data (See above) */ public function toArray(); /** * This method detects file or string. * In case HTML add id attribute and return DOM Object * * @param string $doc parsed file or string */ public function getTableData($doc); }
Parser CSV
CODE
include_once 'Table.php';
include_once 'ITable.php';
class CSVTable extends Table implements ITable{
public $from_file;
public function __construct($doc) {
$this->table_input= $this->getTableData($doc);
parent::__construct();
}
public function getTableData($doc) {
$ext=array('csv');
if(file_exists($doc)){
if(in_array(strtolower(pathinfo($doc,PATHINFO_EXTENSION)),$ext)){
if(is_writable($doc)){
return file_get_contents($doc);
}
}else{
throw new Exception("File type ".pathinfo($doc,PATHINFO_EXTENSION)." does not match expected ".implode(',', $ext)."");
}
} else {
$this->from_file=false;
return $doc;
}
}
public function toArray() {
$i = 0;
$result=array();
$lines=explode(PHP_EOL, $this->table_input);
foreach ($lines as $line){
$i++;
$row=array();
if($i==1){
$row['th']=explode(';', $line);
}else{
$row['td']=explode(';', $line);
}
$result[]=$row;
}
return array('table'=>$result);
}
}
CODE
include_once 'Table.php';
include_once 'ITable.php';
class ASCIITable extends Table implements ITable{
public $from_file;
public function __construct($doc) {
$this->table_input= $this->getTableData($doc);
parent::__construct();
}
public function getTableData($doc) {
$ext=array('txt');
if(file_exists($doc)){
if(in_array(strtolower(pathinfo($doc,PATHINFO_EXTENSION)),$ext)){
$this->from_file=true;
return $doc;
}else{
throw new Exception("File type ".pathinfo($doc,PATHINFO_EXTENSION)." does not match expected ".implode(',', $ext)."");
}
} else {
$this->from_file=false;
return $doc;
}
}
public function toArray() {
$result = array();
$index=0;
if($this->from_file){
foreach (file( $this->table_input) as $line){
if(preg_match('/^\|\.*/', $line,$xx)){
$line= trim($line);
$line= substr($line, 1,-1);
if($index==1){
$result[]=array('th'=>explode('|', $line));
}else{
$result[]=array('td'=>explode('|', $line));
}
}
$index++;
}
return array('table'=>$result);
}else {
$lines=explode(PHP_EOL, $this->table_input);
foreach ($lines as $line){
if(preg_match('/^\|\.*/', $line,$xx)){
$line= trim($line);
$line= substr($line, 1,-1);
if($index==1){
$result[]=array('th'=>explode('|', $line));
}else{
$result[]=array('td'=>explode('|', $line));
}
}
$index++;
}
return array('table'=>$result);
}
}
}