Skip to content

Instantly share code, notes, and snippets.

@hakre
Last active February 9, 2023 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save hakre/5734770 to your computer and use it in GitHub Desktop.
Save hakre/5734770 to your computer and use it in GitHub Desktop.
<?php
/**
* PHP XML to dynamic table
*
* @link http://stackoverflow.com/q/16997835/367456
*/
require('.../Iterator-Garden/src/autoload.php'); // for DecoratingIterator - use development branch
class TableAggregator implements IteratorAggregate
{
private $xml;
public function __construct(SimpleXMLElement $xml) {
$this->xml = $xml;
}
public function getIterator() {
$formatNumber = function ($number) {
if ($number === '0') {
$number = '';
}
return sprintf("%' 2s", $number);
};
$numbersToArray = function (SimpleXMLElement $stringNumbers) use ($formatNumber) {
return array_map($formatNumber, explode('-', $stringNumbers));
};
$tableToRows = function (SimpleXMLElement $table) use ($numbersToArray) {
return new DecoratingIterator($table->children(), $numbersToArray);
};
$tables = new DecoratingIterator(
$this->xml->message->ticketpage->ticket,
$tableToRows
);
return $tables;
}
}
$xml = simplexml_load_file('example.xml');
$tables = new TableAggregator($xml);
foreach ($tables as $table) {
echo new TextTable($table), "\n";
}
class TextTable
{
private $data;
public function __construct($data) {
$this->data = $data;
}
public function __toString() {
$sizes = array();
$data = $this->data;
foreach ($data as $row => $cols) {
foreach ($cols as $index => $value) {
$sizes[$index][$row] = strlen($value);
}
}
$max = array_map('max', $sizes);
$buffer = $this->lineLine($max) . "\n";
foreach ($data as $row) {
$buffer .= $this->lineData($max, $row) . "\n";
$buffer .= $this->lineLine($max) . "\n";
}
return $buffer;
}
private function lineLine($sizes) {
$buffer = "+";
foreach ($sizes as $size) {
$buffer .= str_repeat('-', $size) . "+";
}
return $buffer;
}
private function lineData($sizes, $data) {
$buffer = "|";
foreach ($sizes as $i => $size) {
$buffer .= str_pad($data[$i], $size) . "|";
}
return $buffer;
}
}
class HtmlTable
{
public function __construct(Traversable $table) {
$this->table = $table;
}
function __toString() {
$buffer = "<table>\n";
foreach (new HtmlTableIterator($this->table) as $row) {
$buffer .= " $row\n";
}
$buffer .= "</table>\n";
return $buffer;
}
}
/**
* Class HtmlTableIterator
*
* @see PHP simpleXML how to check if a nested child exists
* @link http://stackoverflow.com/a/16826566/367456
*/
class HtmlTableIterator extends IteratorIterator
{
public function __construct(Traversable $iterator, array $header = NULL) {
$append = new AppendIterator();
$header && $append->append(new ArrayIterator(array($header)));
$append->append(new IteratorIterator($iterator));
parent::__construct($append);
}
public function current() {
$row = '<tr>';
foreach (parent::current() as $cell) {
$row .= "<td>$cell</td>";
}
$row .= "</tr>";
return $row;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment