SimpleXML. Часть 2. XML дерево
В заключительной части цикла статей посвященного работе с SimpleXML, будет рассмотрена довольно распространенная задача: построение XML дерева.
Требования
- Отображение в виде дерева содержимого любого XMLфайла с правильной структурой;
- Возможность сворачивать и разворачивать ветви;
- Атрибуты элементы выводятся в строку рядом с ним;
- Текст элемента так же пишется рядом с названием элемента, но в скобках;
Для того, что бы лучше понять, что же все-таки мы хотим сделать, можно посмотреть на уже готовый пример: http://st-programming.ru/simple_xml/index.php

Как видно, здесь в качестве примера используется все тот же файл с рецептом.
Дерево представляет собой обычный вложенный список. Для добавления функциональности (сворачивание и разворачивание) и нормального внешнего вида используется плагин для (скачать).
Внешний вид и структура
Прежде чем перейти к, непосредственно, разбору xml разберемся сначала с внешним видом и структурой приложения. Создадим три папки: css, images и js. Очевидно это папки для стилей, картинок и js скриптов. Файлы из скаченного архива плагина Treeview, раскидаем по этим папкам. Кроме того, в каталоге css стоит создать еще один файл: main.css – основной файл стилей для нашей странички.
Содержание файла main.css
- body {
- margin: 0;
- padding: 0;
- background-color: #fff;
- font-size: 12px;
- }
- /* Стили отображения атрибутов элемента. */
- .attr {
- margin-left: 5px;
- font-size: 10px;
- color: #ccc;
- }
- /* Стили отображения текста элемента. */
- .text_node {
- font-size: 12px;
- margin-left: 5px;
- color: gray;
- }
Наконец, в главном каталоге создадим файл index.php следующего содержания:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ru" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>XML</title>
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.css" />
<link rel="stylesheet" type="text/css" media="screen" href="/css/jquery.treeview.css" />
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/jquery.treeview.js"></script>
<script type="text/javascript">
$(document).ready(function(){
// Для списка xml_tree, подключаем плагин TreeView
$("#xml_tree").treeview({
animated: "fast" // Задаем скорость анимации
});
});
</script>
</head>
<body>
<ul id="xml_tree" class="filetree">
<!-- Здесь будет строится дерево -->
</ul>
</body>
</html>
Пока, это просто html заготовка. Отображением дерева добавим позже.
Работа с XML
Создадим в корневом каталоге новый файл xmlTree.class.php, как следует из названия, в этом файле будет содержаться xmlTree – класс, для построения XML дерева.
Единственным полем класса будет $xml – корневая ветвь XML документа, типа SimpleXMLElement. Так же будут два метода: закрытый readNode, который, собственно, строит дерево и возвращает результат как строку, и открытый Show, своего рода оболочка для readNode. Кроме того, есть коструктор класса, который принимает имя XML файла как параметр.
Рассмотрим каждый из методов подробно.
Конструктор
Тут, в общем-то, благодаря материалу предыдущей статьи все очевидно.
- class xmlTree {
- private $xml;
- public function __construct( $setFileName ) {
- $this->xml = simplexml_load_file( $setFileName );
- }
- ...
- }
Метод readNode. Построение XML дерева
Этот метод самое важное, что есть в текущей статье. Все, что было до этого, нужно, в общем-то, лишь для оформления. Именно readNode выполняет большую часть требований поставленных ранее.
Метод readNode должен пробежать весь документ, получить все элементы, учитывая их вложенность, также должен получить все атрибуты и текст элементов.
Проще всего такую задачу решить рекурсивно. Хотя, конечно, можно обойтись и без рекурсии, но в данном случае, это совсем не просто.
Метод, в качестве параметра, будет принимать элемент документа. После того, как имя и атрибуты элемента получены, проверяется, есть ли у элемента дочерние ветви. Если есть, тогда циклом для каждой ветви рекурсивно вызывается этот же метод readNode. Таким образом, получается, обработать каждый элемент XML документа любой вложенности.
На выходе должен получатся правильно сформированный html список.
- private function readNode( $node ) {
- $result = "<li>"; // Начинаем новый элемент списка
- $result .= $node->getName(); // Добавляем имя элемента
- // Циклом проходим все атрибуты
- foreach ( $node->attributes() as $name => $value ) {
- // Добавляем атрибуты. Оборачиваем их в тег span с классом стилей attr
- $result .= '<span class="attr">' . $name . " = \"" .
- $value . '"' . '</span>';
- }
- // Работаем с текстом элемента
- $text = trim($node); // Убираем лишние пробелы
- // Если текст у элемента вообще есть
- if ( !empty($text) ) {
- // То добавлем его, заключенного в скобки
- $result .= '<span class="text_node">' . "(" . $text . ")" . '</span>';
- }
- // Если есть дочерние ветви
- if ( count( $node->children() ) ) {
- // Начинаем вложенный список
- $result .= "<ul>";
- // Цикл по доерним ветвям
- foreach ( $node->children() as $chiled_node ) {
- // Каждую из них обраюатывает этой же функцией
- $result .= $this->readNode( $chiled_node );
- }
- $result .= "</ul>";
- }
- $result .= "</li>"; // Закрываем элемент списка
- return $result; // Возвращем сформированный html список
- }
Метод show
Открытый метод. Просто выводится readNode, в качестве параметра, которому передается поле $xml - главная ветвь документа.
- public function show() {
- echo $this->readNode( $this->xml );
- }
На этом с классом xmlTree можно закончить. Вернемся к index.php.
Нужно подключить файл с только что написанным классом. Поместим в начало файла следующий код:
require_once 'xmlTree.class.php';
?>
Теперь уже можно, собственно, написать код для отображения дерева:
<ul id="xml_tree" class="filetree">
<?php
$tree = new xmlTree( "tmp.xml" );
$tree->show();
?>
</ul>
...
И, в итоге, мы получаем правильно сформированное XML дерево, удовлетворяющее поставленным выше требованиям. На этом цикл статей по SimpleXML можно завершить.
xml, алгоритмы, php, jquery
Комментарии (2)
Клевая статья, спасибо автору, заимел для себя много полезного)
$this->readNode
это же рекурсия %/
Добавить комментарий