digitorum.ru

Как меня найти

Профиль

icq: 4415944

Удаляем лишние колонки из таблицы (html) с помощью php

php

Пришла подобная задачка... Сегодня четверг - много печатать мне лень, поэтому сразу к делу.

Класс для постороения "матрицы":

<?php
	
	Class HTML_Table_Object {
		
		/*
		* Строки
		*/
		private $_trs;
		
		/*
		* Конструктор, на вход принимаем html таблички
		*/
		public function __construct($html = '') {
			$this->parse($html);
		}
		
		/*
		* Парсим табличку
		*/
		public function parse($html) {
			if(preg_match_all('~<tr[^>]*>.*?</tr>~is', $html, $trs)) {
				foreach($trs[0] as $i => $tr) {
					$this->_trs[] = new HTML_Table_Object_Tr($tr, $this, $i);
				}
			}
			foreach($this->_trs as $tr) {
				$tr->parse();
			}
		}
		
		/*
		* Получить конкретную строку
		*/
		public function getTrAt($index = 0) {
			return $this->_trs[$index];
		}
		
		/*
		* Схематичный вид полученной матрицы
		*/
		public function schematic() {
			$html = "<table border='1'>";
			foreach($this->_trs as $tr) {
				$html .= $tr->schematic();
			}
			return $html .= "</table>";
		}
		
		/*
		* Пустая ли колонка
		*/
		public function isColumnEmpty($i) {
			foreach($this->_trs as $tr) {
				if(is_object($tr->getTdAt($i))) {
					if(!$tr->getTdAt($i)->isEmpty()) {
						return false;
					}
				}
			}
			return true;
		}
		
		/*
		* Удалить колонку
		*/
		public function deleteColumn($i) {
			foreach($this->_trs as $tr) {
				$tr->deleteTdAt($i);
			}
		}
		
		/*
		* Построить таблицу
		*/
		public function build() {
			foreach($this->_trs as $tr) {
				$tr->merge();
			}
			$html = "<table border='1'>";
			foreach($this->_trs as $tr) {
				$html .= $tr->build();
			}
			return $html .= "</table>";
		}
		
	}
	
?>

 

Класс "строка матрицы":

<?php
	
	Class HTML_Table_Object_Tr {
		
		/*
		* Ячейки
		*/
		private $_tds;
		
		/*
		* Исходный html
		*/
		private $_html = '';
		
		/*
		* ссылка на таблицу
		*/
		private $_table;
		
		/*
		* порядковый номер строки в таблице
		*/
		private $_index = 0;
		
		/*
		* Конструктор, на вход принимает html trки, ссылку на таблицу и порядковый номер
		*/
		public function __construct($html = '', $table = null, $index = 0) {
			$this->_html = $html;
			$this->_table = $table;
			$this->_index = $index;
		}
		
		/*
		* Забрать ячейку
		*/
		public function getTdAt($i = 0) {
			return $this->_tds[$i];
		}
		
		/*
		* Получить следующую tr
		*/
		public function getTable() {
			return $this->_table;
		}
		
		/*
		* Получить индекс
		*/
		public function getIndex() {
			return $this->_index;
		}
		
		/*
		* Ибираем алиасы
		*/
		public function merge() {
			foreach($this->_tds as $i => $td) {
				if($td instanceof HTML_Table_Object_Td_Alias) {
					// если у нас остался алиас - подменяем его на реальную ячейку
					if($td->getTd()->deleted) {
						$this->_tds[$i] = $td->getTd();
						$this->_tds[$i]->deleted = false;
						continue;
					}
					if($td->getTd()->getTrIndex() == $this->getIndex()) {
						$td->getTd()->colspan++;
					} else {
						if($td->getTd()->getIndex() == $td->getIndex()) {
							$td->getTd()->rowspan++;
						}
					}
					unset($this->_tds[$i]);
				}
			}
		}
		
		/*
		* Разобрать строку 
		*/
		public function parse() {
			if(preg_match_all('~<td[^>]*>.*?</td>~is', $this->_html, $tds)) {
				foreach($tds[0] as $i => $td) {
					$index = $this->getFirstEmptyIndexGE($i);
					// резервируем место (так как HTML_Table_Object_Td может добавить в эту строку алиасы на себя)
					$this->_tds[$index] = null;
					// добавляем на указанное место
					$this->_tds[$index] = new HTML_Table_Object_Td($td, $this, $index);
				}
			}
			ksort($this->_tds);
		}
		
		/*
		* Получить первый свободный индекс ячейки, больший или равный указанному
		*/
		public function getFirstEmptyIndexGE($i = 0) {
			if(!isset($this->_tds[$i])) {
				return $i;
			} else {
				while(true) {
					$i++;
					if(!isset($this->_tds[$i])) {
						return $i;
					}
				}
			}
		}
		
		/*
		* Добавить ячейку в строку
		*/
		public function pushTd($td = null) {
			$this->_tds[$td->getIndex()] = $td;
		}
		
		/*
		* Удалить ячейку
		*/
		public function deleteTdAt($i = null) {
			if($i !== null) {
				$this->_tds[$i]->deleted = true;
				unset($this->_tds[$i]);
				$this->_tds = array_values($this->_tds);
			}
		}
		
		/*
		* Количество ячеек в строке
		*/
		public function getTdsCount() {
			return count($this->_tds);
		}
		
		/*
		* Схематичный вид полученной матрицы
		*/
		public function schematic() {
			$html = "<tr>";
			foreach($this->_tds as $td) {
				if(is_object($td)) {
					$html .= $td->schematic();
				}
			}
			return $html .= "</tr>";
		}
		
		/*
		* Построить строку
		*/
		public function build() {
			$html = "<tr>";
			foreach($this->_tds as $td) {
				$html .= $td->build();
			}
			return $html .= "</tr>";
		}
		
	}
	
?>

 

Класс "ячейка матрицы":

<?php
	
	Class HTML_Table_Object_Td {
		
		/*
		* Порядковый номер ячейки
		*/
		private $_index;
		
		/*
		* Ячейка
		*/
		private $_tr;
		
		/*
		* Колспан
		*/
		public $colspan = 1;
		
		/*
		* Роуспан
		*/
		public $rowspan = 1;
		
		/*
		* Флаг о том, что ячейка была удалена
		*/
		public $deleted = false;
		
		/*
		* Контент ячейки
		*/
		private $_content = '';
		
		/*
		* Конструктор, на вход принимает html tdшки, ссылка на tr и порядковый номер
		*/
		public function __construct($html = '', $tr = null, $index = 0) {
			$this->_tr = $tr;
			$this->_index = $index;
			$this->parse($html);
		}
		
		/*
		* Пустая ли ячейка
		*/
		public function isEmpty() {
			return $this->_content == '';
		}
		
		/*
		* Получить инстанс таблицы
		*/
		public function getTable() {
			return $this->_tr->getTable();
		}
		
		/*
		* Получить индекс
		*/
		public function getIndex() {
			return $this->_index;
		}
		
		/*
		* Получить индекс ячейки
		*/
		public function getTrIndex() {
			return $this->_tr->getIndex();
		}
		
		/*
		* Разобрать данные ячейки
		*/
		public function parse($html = '') {
			if(preg_match('~<td([^>]*)>(.*?)</td>~is', $html, $matches)) {
				$attributes = $matches[1];
				$this->_content = trim(str_replace(array('&nbsp;'), array(''), $matches[2]));
				$colspan = 1;
				$rowspan = 1;
				if(preg_match_all('~(colspan|rowspan)=([0-9]+)~', str_replace(array("'", '"'), array('', ''), mb_strtolower($attributes, 'utf-8')), $matches)) {
					foreach($matches[1] as $i => $match) {
						if($match == 'colspan') {
							$colspan = $matches[2][$i];
						}
						if($match == 'rowspan') {
							$rowspan = $matches[2][$i];
						}
					}
				}
				for($i = 0; $i < $colspan; $i++) {
					for($j = 0; $j < $rowspan; $j++) {
						if(!($i ==0 && $j == 0)) {
							$tr = $this->getTable()->getTrAt($this->getTrIndex() + $j);
							$tdIndex = $tr->getFirstEmptyIndexGE($this->getIndex() + $i);			
							$tr->pushTd(new HTML_Table_Object_Td_Alias($this, $tdIndex));
						}
					}
				}
			}
		}
		
		/*
		* Схематичный вид полученной матрицы
		*/
		public function schematic() {
			return "<td>" . $this->getTrIndex() . "-" . $this->getIndex() . "</td>";
		}
		
		/*
		* Построить строку
		*/
		public function build() {
			return "<td" . ($this->colspan > 1 ? (' colspan="' .$this->colspan. '"') : '') . "" . ($this->rowspan > 1 ? (' rowspan="' .$this->rowspan. '"') : '') . ">" . $this->_content . "</td>";
		}
	}
	
?>

 

Класс "алиас на ячейку матрицы" (нужен для обработки colspan и rowspan):

<?php
	
	Class HTML_Table_Object_Td_Alias {
		
		/*
		* Ячейка, на которую ссылаемся
		*/
		private $_td;
		
		/*
		* Псевдоиндекс
		*/
		private $_index = 0;
		
		/*
		* Конструктор, на вход принимаем ячейку, на которую мы ссылаемся
		*/
		public function __construct($td = null, $index = 0) {
			$this->_td = $td;
			$this->_index = $index;
		}
		
		/*
		* Ячейка
		*/
		public function getTd() {
			return $this->_td;
		}
		
		/*
		* Псевдоиндекс
		*/
		public function getIndex() {
			return $this->_index;
		}
		
		/*
		* Алиас всегда считается пустым
		*/
		public function isEmpty() {
			return true;
		}
		
		/*
		* Схематичный вид полученной матрицы
		*/
		public function schematic() {
			return "<td>" . $this->_td->getTrIndex() . "-" . $this->_td->getIndex() . "+</td>";
		}
	}
	
?>

 

Собственно как-то так... Кормим скрипту подобную табличку:

Cell    
Cell
Cell      
      Cell

Серым цветом отмечена колонка, которую надо удалить.

<?php
	$table = new HTML_Table_Object($table);
?>

 

Выведем получившуюся матрицу:

<?php
	print $table->schematic();
?>

 

0-0 0-0+ 0-2 0-3
0-0+ 0-0+ 1-2 1-2+
2-0 2-1 2-2 2-3
3-0 3-1 3-2 3-3

Плюсами отмечены алиасы на ячейку (ведь ячейка с колспанами и роуспанами - все равно это ОДНА ячейка).

Ну и далее чистим табличку от пустых колонок:

<?php
	for($i=$table->getTrAt(0)->getTdsCount()-1; $i>=0; $i--) {
		if($table->isColumnEmpty($i)) {
			$table->deleteColumn($i);
		}
	}
	print $table->schematic();
	print $table->build();
?>

 

Результат:

0-0 0-2 0-3
0-0+ 1-2 1-2+
2-0 2-2 2-3
3-0 3-2 3-3

 

Cell
Cell
Cell
Cell

В общем то ровно то, что я и хотел получить.

Скрипт не идеальный, но, вроде бы, работает. Найдете баги - пишите

Возможно будет интересно: