2013-06-08 4 views
0

Я пытаюсь создать динамическую таблицу на основе XML. Выводимый XML-состоит в следующем:PHP XML для динамической таблицы

<tickets xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <status>1</status> 
    <message> 
     <ticketpage> 
      <ticket> 
       <row1>0-10-27-30-45-0-0-0-80</row1> 
       <row2>0-15-0-38-0-51-62-0-85</row2> 
       <row3>5-0-0-37-0-57-60-77-0</row3> 
      </ticket> 
      <ticket> 
       <row1>0-0-20-33-0-56-68-0-90</row1> 
       <row2>8-0-0-0-49-0-64-71-84</row2> 
       <row3>1-18-22-32-0-59-0-0-0</row3> 
      </ticket> 
      <ticket> 
       <row1>0-0-23-0-47-58-67-0-86</row1> 
       <row2>4-16-0-0-43-53-0-0-88</row2> 
       <row3>3-0-28-35-0-0-65-72-0</row3> 
      </ticket> 
      <ticket> 
       <row1>0-19-26-0-48-52-0-74-0</row1> 
       <row2>0-0-21-0-40-0-63-75-82</row2> 
       <row3>9-11-0-34-41-0-0-76-0</row3> 
      </ticket> 
      <ticket> 
       <row1>0-12-29-36-44-0-0-78-0</row1> 
       <row2>6-14-0-39-0-0-69-0-89</row2> 
       <row3>2-0-0-0-0-54-66-70-81</row3> 
      </ticket> 
      <ticket> 
       <row1>0-17-25-0-46-0-0-73-87</row1> 
       <row2>0-0-24-0-42-50-61-79-0</row2> 
       <row3>7-13-0-31-0-55-0-0-83</row3> 
      </ticket> 
     </ticketpage> 
    </message> 
</tickets> 

Каждый «билет» является новая таблица, каждая «строка» является строка и каждое число в строке представляет собой столбец (за 0 исключением того, что будет пустой клетка).

Я знаю, что должен использовать SimpleXML для PHP, но я понятия не имею как.

Как мне это сделать?

+0

Общий учебник о SimpleXMLElement можно найти здесь: http://php.net/simplexml.examples-basic - вы начинаете с этим, написав некоторый код, загружающий XML-документ. Затем вы разбираете его, как правило, итерацией по нему. – hakre

ответ

2

Я дал обширный пример в вопросе PHP simplexml xpath search for value in an ELEMENT containing tab delimited text?, который показывает, как можно манипулировать SimpleXMLElement на лету, содержащего закодированные данные, превращая его в более доступных данных.

Это можно сделать аналогичным образом в вашем случае, однако на этот раз я хотел бы показать, как это можно сделать с помощью пользовательских итераторов.

Но сначала рассмотрим, как можно представить таблицу: Таблица состоит из строк и столбцов. Таким образом, мы могли выполнять итерацию по строкам, и каждая строка могла быть итератором столбцов.

И с вашим вопросом, есть и другой итератор над таблицами. Поэтому в псевдокоде это может выглядеть так:

foreach($tables as $table) 
{ 
    foreach ($table as $rows) { 
     foreach ($rows as $column) { 
     } 
    } 
} 

Выполнение вывода где-то вокруг этого. Так, например, если у нас есть Итератор, способный перебирать строки и столбцы, чтобы преобразовать их в таблицу (например, как обычный текст для демонстрационных целей), псевдокод можно свести к следующему:

foreach($tables as $table) 
{ 
    echo new TextTable($table); 
} 

Как показано на этом примере, проблема уже была уменьшена, чтобы отобразить одну таблицу, поскольку все таблицы соответствуют одной и той же структуре. Сейчас я не показываю TextTable, но это не является дополнительным интересом. Если вы ищете итератор, который выводит таблицу HTML, следуя той же итерации, см. Связанный вопрос выше, он имеет HtmlTableIterator, который выполняет большую часть работы. Но прямо сейчас давайте посмотрим, как создать итератор по строкам и столбцам.

Для этого я представляю вам существующий класс итератора с именем DecoratingIterator. Он позволяет украшать каждый элемент текущего на итерации. Это довольно гибко, потому что мы можем использовать его для составления финального итератора таблицы довольно гибким способом с небольшими шагами.

Решите все проблемы, с которыми вы сталкиваетесь, шаг за шагом. Прежде всего, нужна функция, чтобы превратить число 0 в пустую строку. Давайте создадим функцию для этого (и я также добавить еще некоторое форматирование предваряя с пробелами, если это необходимо, чтобы получить длину двух):

$formatNumber = function($number) 
{ 
    if ($number === '0') { 
     $number = ''; 
    } 

    return sprintf("%' 2s", $number); 
}; 

Следующая задача решить это превратить SimpleXMLElement чисел в нечто Еогеасп которые являются форматированными числами.Давайте просто писать, а также и использовать предыдущей функции, чтобы помочь сделать это:

$numbersToArray = function($stringNumbers) use ($formatNumber) { 
    return array_map($formatNumber, explode('-', $stringNumbers)); 
}; 

Вау, это было коротким. Следующая задача для решения состоит в том, чтобы превратить все строки одной таблицы в эти массивы чисел. Ну, опять же, мы делаем это с помощью последней функции:

$tableToRows = function(SimpleXMLElement $table) use ($numbersToArray) { 
    return new DecoratingIterator($table->children(), $numbersToArray); 
}; 

И, наконец, одна проблема остается: Весь XML должен быть превращена в итератор всех таблиц. Снова с предыдущей функцией это снова стало проще:

$tables = new DecoratingIterator(
    $xml->message->ticketpage->ticket, 
    $tableToRows 
); 

Ничего себе. Возможно, немного долго, давайте обзор:

$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(
    $xml->message->ticketpage->ticket, 
    $tableToRows 
); 

Все эти строки кода сделать, это обеспечить $tables итератора можно использовать для отображения таблицы. Таким образом, чтобы сделать это более легкий в использовании, мы обернуть это в класс его собственного и сигналом PHP, что этот класс может агрегировать итератор, который работает через интерфейс IteratorAggregate:

class TableAggregator implements IteratorAggregate 
{ 
    private $xml; 

    public function __construct(SimpleXMLElement $xml) 
    { 
     $this->xml = $xml; 
    } 

    public function getIterator() 
    { 
     # ... code to create the tables iterator 

     return $tables; 
    } 
} 

Хорошо, что, вероятно, было много до сих пор. Лучше показать пример использования-сейчас, чтобы сделать видимой почему агрегация имеет смысл здесь:

$xml = simplexml_load_file('example.xml'); 

$tables = new TableAggregator($xml); 

foreach ($tables as $table) { 
    echo new TextTable($table), "\n"; 
} 

Как показывает этот пример, его, потому что это простой в использовании. Также, если у нас есть другие потребности в форматировании, мы могли бы создать другой aggregator - это просто. Давайте посмотрим примерный вывод:

+--+--+--+--+--+--+--+--+--+ 
| |10|27|30|45| | | |80| 
+--+--+--+--+--+--+--+--+--+ 
| |15| |38| |51|62| |85| 
+--+--+--+--+--+--+--+--+--+ 
| 5| | |37| |57|60|77| | 
+--+--+--+--+--+--+--+--+--+ 

+--+--+--+--+--+--+--+--+--+ 
| | |20|33| |56|68| |90| 
+--+--+--+--+--+--+--+--+--+ 
| 8| | | |49| |64|71|84| 
+--+--+--+--+--+--+--+--+--+ 
| 1|18|22|32| |59| | | | 
+--+--+--+--+--+--+--+--+--+ 

+--+--+--+--+--+--+--+--+--+ 
| | |23| |47|58|67| |86| 
+--+--+--+--+--+--+--+--+--+ 
| 4|16| | |43|53| | |88| 
+--+--+--+--+--+--+--+--+--+ 
| 3| |28|35| | |65|72| | 
+--+--+--+--+--+--+--+--+--+ 

+--+--+--+--+--+--+--+--+--+ 
| |19|26| |48|52| |74| | 
+--+--+--+--+--+--+--+--+--+ 
| | |21| |40| |63|75|82| 
+--+--+--+--+--+--+--+--+--+ 
| 9|11| |34|41| | |76| | 
+--+--+--+--+--+--+--+--+--+ 

+--+--+--+--+--+--+--+--+--+ 
| |12|29|36|44| | |78| | 
+--+--+--+--+--+--+--+--+--+ 
| 6|14| |39| | |69| |89| 
+--+--+--+--+--+--+--+--+--+ 
| 2| | | | |54|66|70|81| 
+--+--+--+--+--+--+--+--+--+ 

+--+--+--+--+--+--+--+--+--+ 
| |17|25| |46| | |73|87| 
+--+--+--+--+--+--+--+--+--+ 
| | |24| |42|50|61|79| | 
+--+--+--+--+--+--+--+--+--+ 
| 7|13| |31| |55| | |83| 
+--+--+--+--+--+--+--+--+--+ 

Весь пример одного взгляда: https://gist.github.com/hakre/5734770

+0

Святая корова, это действительно просветительская. –

+0

Странно, он говорит, что не может найти класс DecoratingIterator. Однако я добавил «Итератор-сад». –

+1

@AlexGorcea: Возьмите ветку развития итератора-сада. Извините, я этого не делал. Этот класс, однако, связан также и в readme, Он не написан мной в первую очередь, но довольно много лет. См. Https://github.com/hakre/Iterator-Garden/blob/development/src/DecoratingIterator.php и первоначально здесь: https://code.google.com/p/cvphplib/source/browse/trunk/cvphplib /code/iterator_madness.inc.php?r=6 – hakre

1

Вы можете попробовать это:

<?php 
$str = '<tickets xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
      <status>1</status> 
      <message> 
       <ticketpage> 
        <ticket> 
         <row>0-10-27-30-45-0-0-0-80</row> 
         <row>0-15-0-38-0-51-62-0-85</row> 
         <row>5-0-0-37-0-57-60-77-0</row> 
        </ticket> 
       </ticketpage> 
      </message> 
     </tickets>'; 
$dom = new SimpleXMLElement($str); 
foreach ($dom->message->ticketpage->ticket as $ticket) { 
    echo '<table border=1>'; 
    foreach($ticket->row as $row){ 
     $cellList = explode('-',$row); 
     echo '<tr>'; 
     foreach ($cellList as $cell){ 
      echo '<td>', $cell, '</td>'; 
     } 
     echo '</tr>'; 
    } 
    echo '</table>'; 
} 
+0

Отлично работает, я даже преобразовал нули в пустые места (для меня это очень важно). –

+0

Однако он просто выводит один билетный узел. –

+0

потому что данные примера имеют только один узел – VNTeck