Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Котеров Д. В., Костарев А. Ф. - PHP 5. 2-е издание (В подлиннике) - 2008

.pdf
Скачиваний:
6114
Добавлен:
29.02.2016
Размер:
11.36 Mб
Скачать

724

Часть VI. XML в PHP 5

$nodepath = $path;

$n = strrpos($path, '/'); // позиция последнего символа / if ($n >= 0)

$nodepath = substr($path,0,$n); return $nodepath;

}

/**

*Сформировать путь до следующего узла

*@return string — путь, указывающий следующий узел */

function NextSiblingRef() {

 

 

global $path;

// путь до отображаемого узла

$nodepath = $path;

 

 

$n = strrpos($path, '/');

// позиция последнего символа /

if ($n >= 0) {

 

 

$n++;

 

 

if (substr($path,$n,1) == '@') $n++; // узел атрибута

$parentpath = substr($path,0,$n);

// путь до родителя

$local = substr($path,$n);

// номер в уровне

$nodepath = "$parentpath" . ($local+1);

}

return $nodepath;

}

/**

*Сформировать путь до предыдущего узла

*@return string — путь, указывающий предыдущий узел */

function PreviousSiblingRef() {

 

global $path;

// путь до отображаемого узла

$n = strrpos($path, '/');

// позиция последнего символа /

$nodepath = $path;

 

 

if ($n >= 0) {

 

 

$n++;

 

 

if (substr($path, $n, 1) == '@') $n++; // узел атрибута

$parentpath = substr($path, 0, $n);

// путь до родителя

$local = substr($path,$n);

// номер в уровне

$nodepath = "$parentpath" . ($local — 1);

}

return $nodepath;

}

/**

*Сформировать путь до первого дочернего элемента

*@return string — путь, указывающий первый дочерний элемент */

function FirstChildRef() {

global $path; // путь до отображаемого узла $nodepath = $path;

$nodepath .= "/1"; return $nodepath;

}

Глава 37. DOM1 — объектная модель XML-документа

725

/**

*Сформировать путь до последнего дочернего элемента

*@param int $nlast — номер последнего дочернего элемента

*@return string — путь, указывающий последний дочерний элемент */

function LastChildRef($nlast) {

global $path; // путь до отображаемого узла $nodepath = $path;

$nodepath .= "/$nlast"; return $nodepath;

}

/**

*Сформировать путь до дочернего элемента $num

*@param int $num — номер дочернего узла

*@return string — путь, указывающий дочерний элемент $num */

function ChildRef($num) {

global $path; // путь до отображаемого узла $nodepath = "$path/" . ($num + 1); // 0-й элемент адресуется как 1-й return $nodepath;

}

/**

*Сформировать путь до атрибута $num

*@param int $num — номер атрибута

*@return string — путь, указывающий на атрибут $num */

function AttrRef($num) {

global $path; // путь до отображаемого узла $nodepath = "$path/@" . ($num + 1);

return $nodepath;

}

Все функции получают адрес требуемого узла, преобразуя адрес $path текущего узла.

Функция ParentRef() формирует адрес родительского узла, удаляя часть адреса после последнего символа /. Адрес /4/3/5 преобразуется в /4/3.

Функция NextSiblingRef() — адрес следующего узла данного подуровня, увеличивая на единицу номер текущего узла. Адрес дочернего узла /4/3/5 преобразуется в

/4/3/6. Адрес атрибута /4/3/5/@1 — в /4/3/5/@2.

Функция PreviousSiblingRef() — адрес предыдущего узла данного подуровня, увеличивая на единицу номер текущего узла. Адрес дочернего узла 4/3/5 преобразуется в 4/3/4. Адрес атрибута /4/3/5/@2 — в /4/3/5/@1.

Функция FirstChildRef() — адрес первого дочернего элемента путем добавления строки /1 к текущему адресу. Адрес 4/3/5 преобразуется в 4/3/5/1.

Функции LastChildRef() передается номер последнего узла в списке дочерних узлов (свойство length списка nodeList). Адрес 4/3/5 преобразуется в 4/3/5/номер_

последнего_узла.

Функция ChildRef() возвращает адрес n-го дочернего узла.

726

Часть VI. XML в PHP 5

Функция AttrRef() — адрес атрибута с номером $num, добавляя к адресу текущего узла строку /@$num.

Итак, нам осталось лишь привести текст основного скрипта shownode.php, отображающего свойства узла (листинг 37.23).

Листинг 37.23. Файл shownodeinfo/shownode.php

<?php ## Скрипт отображения свойств узла. require_once 'unicode.inc';

require_once 'nodetypes.inc'; require_once 'domnodetitle.inc'; require_once 'print_properties.inc'; require_once 'path.inc'; require_once 'showref.inc'; require_once 'refs.inc';

if (!isset($_GET["xmlfile"])) $xmlfile='prog.xml'; else $xmlfile=$_GET["xmlfile"];

if (!$xmlfile) $xmlfile='prog.xml';

if (!isset($_GET["path"])) $path='/'; else $path=$_GET["path"];

while (strstr($path, '//')) // заменить все // на / $path = str_replace('//', '/', $path);

$dom = new domDocument('1.0'); $dom->preserveWhiteSpace = false; $dom->load($xmlfile);

$node = getNodeByPath($dom, $path);

$title = "Свойства узла\n" . domNodeTitle($node) . "\n(путь:" . utf8decode($path) . ")";

?>

<html>

<head>

<link rel="stylesheet" type="text/css" href="style.css"> <title><?php echo $title?></title>

</head>

<body>

<h1><?php echo nl2br($title)?></h1> <?php print_domNodeProperties($node)?> <hr>

<h1>Содержание узла</h1> <pre>

<?php

$dom->formatOutput = true; if ($node !== $dom)

echo htmlspecialchars(utf8decode($dom->saveXML($node))); else

echo htmlspecialchars($dom->saveXML());

Глава 37. DOM1 — объектная модель XML-документа

727

?>

</pre>

</body>

Скрипту передаются следующие параметры:

xmlfile — адрес анализируемого XML-файла;

path — адрес анализируемого узла в XML-файле.

Если адрес XML-файла не задан, то используется стандартный файл prog.xml, описанный нами в гл. 36. Если адрес анализируемого узла не определен, анализируется корневой узел.

Указанный XML-файл загружается методом load().

Приведенная в листинге 37.18 функция getNodeByPath() отыскивает требуемый узел в документе, который отображается описанной в листинге 37.20 функцией print_domNodeProperties(). В конце страницы метод saveXML() отображает полный текст узла в формате XML.

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

Для полной картины приведем еще код HTML-страницы выбора XML-файла (листинг 37.24).

Листинг 37.24. Файл shownodeinfo/index.php

<!-- HTML-страница выбора XML-файла для анализа index.html. --> <HTML>

<HEAD>

<TITLE>Страница выбора XML-файла для анализа</TITLE> </HEAD>

<BODY>

<CENTER>

<FORM ACTION="shownode.php">

Введите URL-адрес XML-файла для анализа <BR />

<INPUT NAME="xmlfile" SIZE="80" /> <BR />

<INPUT TYPE="submit" NAME="Перейти к странице анализа" /> </FORM>

</CENTER>

</BODY>

Вид страницы показан на рис. 37.4.

В поле адреса пользователь вводит адрес XML-файла — это может быть локальный адрес файла на сервере или URL любого XML-файла в Интернете, например, httpадрес рассматриваемого нами (рис. 37.4) файла prog.xml: http://php5xml.nevod.ru /scripts/dom1/shownodeinfo/prog.xml.

728

Часть VI. XML в PHP 5

 

 

 

 

 

 

 

 

Рис. 37.4. Вид страницы выбора XML-файла для просмотра

Свойства объектов подклассов класса domNode

Итак, приведенный нами скрипт позволяет отобразить информацию по любому узлу XML-документа. Но он отображает лишь свойства, общие для всех типов узлов. Объект каждого типа узла, являясь подклассом обобщенного класса domNode, имеет дополнительные свойства. Если вы обратили внимание, в листинге 37.20 мы оставили функцию-заглушку showsubclassproperties(), отображающую свойства, специфичные для каждого типа узла. Полный текст этой программы приведен в листинге 37.25.

Листинг 37.25. Файл shownodeinfo/showsubclassprop.inc

<?php ## Выбор программы отображения свойств конкретного узла. require_once 'showdocumentprop.inc';

require_once 'showdtdprop.inc'; require_once 'showelementprop.inc'; require_once 'showpiprop.inc'; require_once 'showattrprop.inc'; require_once 'showcharacterdataprop.inc'; require_once 'showtextprop.inc'; require_once 'showentityprop.inc';

/**

*Отобразить свойства конкретного узла

*@param domNode $domnode — отображаемый узел

* @return void — HTML-код помещается в буфер вывода

*/

function showSubclassProperties($domnode) { ?>

><tr

><td

Глава 37. DOM1 — объектная модель XML-документа

729

>Свойства типа

 

 

<b><?php echo nodeTypeToString($domnode->nodeType)?></b>:

 

</td

 

 

><td

 

 

><table<?php

 

 

switch ($domnode->nodeType) {

 

 

case XML_DOCUMENT_NODE:

// Документ

 

showDocumentProperties($domnode); break;

 

case XML_ELEMENT_NODE:

// Элемент

 

showElementProperties($domnode); break;

 

case XML_COMMENT_NODE:

// Комментарий

 

// Класс Comment, подкласс CharacterData

 

showCharacterDataProperties($domnode); break;

 

case XML_DOCUMENT_TYPE_NODE:

// Описатель типа документа

 

showDTDProperties($domnode); break;

 

case XML_PI_NODE:

// Команды приложения

 

showPIProperties($domnode); break;

 

case XML_ATTRIBUTE_NODE:

// атрибут

 

showAttributeProperties($domnode); break;

 

case XML_ENTITY_REF_NODE:

// Ссылка на компонент

 

nullProperties($domnode); break;

 

case XML_ENTITY_DECL_NODE:

// Описание компонента

 

showEntityDeclProperties($domnode); break;

 

case XML_TEXT_NODE:

// Текстовый узел

 

// Класс Text, подкласс CharacterData

 

showCharacterDataProperties($domnode);

 

showTextProperties($domnode); break;

 

case XML_CDATA_SECTION_NODE:

// Секция CDATA

 

// Класс CDATASection, подкласс Text showCharacterDataProperties($domnode); showTextProperties($domnode); break;

}?>

></table

></td

></tr<?php

}

/**

*Заглушка для неотображаемых свойств

*@param domNode $domnode — отображаемый узел

*@return void

*/

function nullProperties($domnode) {

// Дополнительные свойства отсутствуют.

}

Свойства отображаются в отдельной строке (Свойства типа) в виде таблицы. Для каждого типа узла (подкласса) программа вызывает соответствующую функцию отображения его свойств в отдельной ячейке таблицы. Как видно из текста программы, узлы типа XML_COMMENT_NODE, XML_CDATA_SECTION_NODE, XML_ENTITY_REF_NODE не имеют дополнительных свойств (вызывается пустая функция).

730

Часть VI. XML в PHP 5

Каждый тип узла описывается в PHP 5 отдельным классом, являющимся подклассом корневого класса domNode. Часть свойств подкласса дублирует свойства, имеющиеся в классе domNode (например, свойство target подкласса domProcessingInstruction дублирует свойство nodeName класса domNode), часть несет дополнительную информацию.

Свойства класса domDocument

Класс domDocument является подклассом класса domNode (рис. 37.5).

Список возможных дочерних узлов узла класса domDocument показан на рис. 37.6.

 

DocumentType

 

Comment

domNode

Document

 

 

ProcessingInstructions

domDocument

Element

Рис. 37.5. Иерархия суперклассов

Рис. 37.6. Список допустимых дочерних узлов

класса domDocument

узла Document

Часть свойств (formatOutput, validateOnParse, resolveExternals, preserveWhiteSpace, substituteEntities, actualEncoding, encoding), относящихся к вводу и выводу XML-документа, мы уже описали в предыдущих разделах. Рассмотрим остальные свойства.

Как мы уже описывали ранее, каждый документ (узел класса domDocument) должен иметь один, и только один корневой элемент, а также может иметь один описатель типа документа (DocType). Для доступа к этим узлам имеет смысл написать специальные функции (листинг 37.26).

Листинг 37.26. Файл shownodeinfo/getroot.php

<?php ## Функции доступа к корневому узлу и узлу DocType. /**

*Найти корневой элемент

*@param domDocument $dom — XML-документ

* @return domNode

— корневой элемент XML-документа

*/

 

function getroot($dom) { $children = $dom->childNodes; foreach ($children as $child) {

if ($child->nodeType == XML_ELEMENT_NODE) return $child;

}

Глава 37. DOM1 — объектная модель XML-документа

731

return NULL;

}

/**

*Найти описатель DTD

*@param domDocument $dom — XML-документ

* @return domNode

— корневой элемент XML-документа

*/

 

function getDTD($dom) {

 

$children = $dom->childNodes; foreach ($children as $child) {

if ($child->nodeType == XML_DOCUMENT_TYPE_NODE) return $child;

}

return NULL;

}

Но использовать данные функции нет необходимости — объект класса domDocument имеет два свойства, указывающие непосредственно на эти узлы:

doctype — указатель на описатель DocType документа;

documentElement — указатель на корневой элемент документа.

Для адресации этих узлов (получения номера в списке дочерних элементов) мы используем функции getrootnumber() и getDocTypenumber() (листинг 37.27). Для формирования ссылки на страницу отображения этих узлов предназначена функция showref(), приведенная в листинге 37.21.

Листинг 37.27. Файл shownodeinfo/showdocumentprop.inc

<?php ## Отображение свойств класса domDocument. /**

*Отобразить свойства узла класса domDocument в формате HTML

*@param domDocument $domdocument — узел XML-документа

* @return void — HTML-код помещается в буфер вывода

*/

function showDocumentProperties($domdocument) { ?>

><TR

><TD>documentURI (Адрес):</TD

><TD><?php echo $domdocument->documentURI?></TD ></TR

><TR

><TD>version (версия):</TD

><TD><?php echo $domdocument->version?></TD ></TR

><TR

><TD>encoding (кодировка):</TD

><TD><?php echo $domdocument->encoding?></TD ></TR

><TR

><TD>ActualEncoding (Текущая кодировка)):</TD

732

Часть VI. XML в PHP 5

><TD><?php echo $domdocument->actualEncoding?></TD ></TR

><TR

><TD>DTD</TD

><TD><?php

showref('/'. getDTDnumber($domdocument), $domdocument->doctype) ?></TD

></TR

><TR

><TD>Root</TD><TD><?php

showref('/'. getrootnumber($domdocument), $domdocument->documentElement) ?></TD

></TR

><TR

><TD>standalone (Автономный):</TD

><TD><?php echo ($domdocument->standalone? 'Да' : 'Нет')?></TD ></TR

><TR

><TD>formatOutput(Форматировать):</TD

><TD><?php echo ($domdocument->formatOutput? 'Да' : 'Нет')?></TD ></TR

><TR

><TD>validateOnParse(Проверять при анализе):</TD

><TD><?php echo ($domdocument->validateOnParse?'Да':'Нет')?></TD ></TR

><TR

><TD>resolveExternals(Разрешать внешние ссылки):</TD

><TD><?php echo ($domdocument->resolveExternals? 'Да' : 'Нет')?></TD ></TR

><TR

><TD>preserveWhiteSpace(Подавлять незначащие пробелы):</TD

><TD><?php echo ($domdocument->preserveWhiteSpace? 'Да' : 'Нет')?></TD ></TR

><TR

><TD>substituteEntities(Подставлять компоненты):</TD

><TD><?php echo ($domdocument->substituteEntities? 'Да' : 'Нет')?></TD ></TR

<?php

}

/**

*Найти номер корневого элемента

*@param domDocument $domdocument — узел XML-документа

*@return int — номер корневого элемента в списке дочерних элементов */

function getrootnumber($domdocument) { $children =$domdocument->childNodes;

for ($ret=0; $ret<$children->length; $ret++) { $child = $children->item($ret);

if ($child->nodeType == XML_ELEMENT_NODE) break;

}

Глава 37. DOM1 — объектная модель XML-документа

733

$ret++; // адрес начинается с 1, следовательно, увеличиваем на 1 return $ret;

}

/**

*Найти номер описателя DTD

*@param domDocument $domdocument — узел XML-документа

*@return int — номер описателя DTD в списке дочерних элементов */

function getDTDnumber($domdocument) { $children = $domdocument->childNodes;

for ($ret=0; $ret<$children->length; $ret++) { $child = $children->item($ret);

if ($child->nodeType == XML_DOCUMENT_TYPE_NODE) break;

}

$ret++; // адрес начинается с 1, следовательно, увеличиваем на 1 return $ret;

}

Результат работы этой функции показан на рис. 37.7.

Рис. 37.7. Отображение свойств класса domDocument

Тут вы можете оставить комментарий к выбранному абзацу или сообщить об ошибке.

Оставленные комментарии видны всем.