PHP и XML

Содержание:

Введение в XML

Xml — это язык разметки, являющий собой способ представления структурированных данных.  Он:

  • Универсальный, расширяемый.
  • Независимый от платформы, операционной системы.
  • Позволяет сохранять описательные данные (метаданные).

В xml в качестве некой единицы измерения представлен “документ”. Это некая законченная порция данных.

Документ может содержать:

  • данные (само содержание),
  • структуру (иерархичность данных),
  • представление (то, как все это сможет увидеть конечный пользователь).

Различия XML и HTML

HTML описывает ИЗ ЧЕГО СОСТОИТ и КАК отображать документ.

Пример:

<table>
<tbody>
<tr>
<td>NAME</td>
<td>IVAN</td>
</tr>
<tr>
<td>SALARY</td>
<td>1000000</td>
</tr>
</tbody>
</table>

XML определяет ЗНАЧЕНИЕ и ОТНОШЕНИЕ данных

<employee>

<name>IVAN</name>

<salary>1000000</salary>

</employee>

XML теги

XML использует теги для определения данных.

Рисунок №1 - пример тега xml

Рисунок №1 — пример тега xml

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

<employee>

<name>Ivan</name>

<salary>100000</salary>

</employee>

Синтаксис, грамматика и семантика элементов

  • Синтаксис — правила записи элементов разметки.
  • Грамматика — отношения элементов разметки друг к другу.
  • Семантика — смысловые значения элементов разметки.

В xml на базовом уровне есть только синтаксис. Грамматики нет, так как изначально не определено ни одного тега. Семантики изначально также нет, по той же причине. Все это появляется только в процессе создания своих тегов и и привязывания к ним того или иного смысла.

Более подробно о синтаксисе

Рассмотрим, из чего состоит xml документ и его структуру (рис. 2)

Пример xml документа

Рисунок №2 — Пример xml документа

Декларация (инструкция по обработке) не несет в себе данных, а несет инструкции о том, как их обрабатывать. Инструкций может быть любое количество. Например, у нас может быть такой документ:

<?xml version="1.0" encoding="UTF-8"?>

<?format drive="c"?>

<data>

</data>

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

Любой элемент в xml регистрозависимый. Т.е. теги можно писать как в нижнем, так и в верхнем регистре, главное единообразие.

Все теги в xml должны быть закрыты. В тех случаях, когда тег не подразумевает в себе содержимого, используется сокращенный синтаксис.

  • стандартный вариант — <exists></exists>
  • сокращенный вариант — <exists />

При возникновении необходимости использовать внутри тега строку, содержащую запрещенные символы (>,<,&),  используется конструкция CDATA. Т.е. мы указываем, что содержание нужно воспринимать просто как строку, а не анализировать содержание.

Пример

<?xml version="1.0" encoding="UTF-8"?>

<?format drive="c"?>

<data>

<desc>

<![CDATA[

Тут идет текст, в котором используются запрещенные символы >, <, &.

]]>

</desc>

</data>

Все элементы могут содержать атрибуты. Значения атрибутов, по правилам синтаксиса, должны быть в двойных кавычках. Некоторые парсеры xml документов позволяют использовать в атрибутах одинарные. Повторяющихся атрибутов в рамках одного элемента не должно быть.

Well-formed (синтаксически корректный) и валидный xml

Well-formed — данный статус документ получает в том случае, если он соответствует всем правилам синтаксиса. По сути, если при открытии браузером документа он не выдал ошибку, значит он корректен.

Валидный документ — это, во-первых, синтаксически корректный документ, а во-вторых, соответствующий заранее определенному набору правил или структуре документа.

Для описания структуры документа используются:

  • DTD — document Type Definition
  • XML схемы

Работа с XML средствами PHP

Simple API for XML (SAX)

SAX — этот инструмент позволяет читать xml документ и получать из него данные.  Создать или же, например, изменить xml документ при помощи данного инструмента невозможно.

Логика работы проста, — парсер имеет три события:

  • когда он обнаруживает открывающий тег,
  • когда он обнаруживает закрывающий тег,
  • когда он обнаруживает содержимое тега.

Т.е. необходимо описать функции, которые отработают, когда будут происходить вышеперечисленные события.

Пример

// Создание парсера

$sax = xml_parser_create("utf-8");

//Функция, которая вызывается, когда парсер обнаруживает открывающий тег

/*

$parser - парсер передает сам себя,

$tag - в этот параметр будет передан открывающий тег в верхнем регистре,

$attributes - если у тега есть атрибуты, то в этот параметр придет ассоциативный массив

*/

function onStart($parser, $tag, $attributes){

if($tag != "CATALOG" & $tag != "BOOK")

    echo "<td>";

if($tag == "BOOK")

    echo "<tr>";

}

//Функция, которая вызывается, когда парсер обнаруживает закрывающий тег

/*

Параметры заполняются аналогично. Параметр $attributes отсутствует.

*/

function onEnd($parser, $tag){

if($tag != "CATALOG" & $tag != "BOOK")

    echo "</td>";

if($tag == "BOOK")

    echo "</tr>";

}

//Функция, которая вызывается, когда парсер обнаруживает содержимое тега

/*

$parser - парсер передает сам себя,

$text - в этот параметр передается содержимое тега

*/

function onText($parser, $text){

    echo "$text";

}

//При помощи функции xml_set_element_handler, мы передаем имена функций для

//события "открывающий тег" и "закрывающий тег"

xml_set_element_handler($sax, "onStart", "onEnd");

//При помощи функции xml_set_character_data_handler,

//передаем имя функции для события "содержимое тега"

xml_set_character_data_handler($sax, "onText");

//Запускаем парсер в том месте, где нужно вывести считанные данные

/*

Вторым параметром передаем xml файл в виде строки

*/

xml_parse($sax, file_get_contents("catalog.xml"));

//В результате получим такой HTML

/*

<tr>

<td>Братья Карамазовы</td>

<td>Великая книга</td>

<td>1000</td>

</tr>

<tr>

<td>Страдания юного Вертера</td>

<td>Стоящая книга</td>

<td>100</td>

</tr>

*/

DOM

DOM (Document Object Model) — это интерфейс, позволяющий программам управлять содержимым документов xml, а также изменять их структуру. Данный интерфейс представляет xml документ в виде дерева узлов. Работа с DOM парсером является самым ресурсоемким процессом, так как весь документ записывается в память и в памяти строится дерево узлов.

Например, документ:

<catalog>

  <book>

    <author>

    Достоевский

    </author>

    <title>

    Братья Карамазовы

    </title>

  </book>

  <book>

    <author>

    Гете

    </author>

    <title>

    Страдания юного Вертера

    </title>

  </book>

</catalog>

Будет иметь следующий вид (рис. 3)

Пример построенного DOM дерева xml документа

Рисунок №3 — Пример построенного DOM дерева xml документа

Идея заключается в том, что все, что есть в xml документе это — узел. В том числе и комментарий. И каждый узел является объектом. Логика аналогичная с DOM деревом html и тем как с ним работает JavaScript. Т.е. все узлы предстают в виде объектов, у которых есть свойства и методы. Тут есть важный момент, логично предположить, что если обратиться к свойству или методу объекта, которого у него нет, мы получим ошибку. И для того, чтобы такую ошибку не получить нужно знать, какие есть типы узлов и какие свойства и методы доступны каждому типу. Типы узлов xml документа представлены на рисунке 4.

типы узлов xml документа

Рисунок №4 — типы узлов xml документа

Схематично, связь между узлами можно представить следующим образом (рис 5).

связь между узлами

Рисунок №5 — Связь между узлами

Базовое использование DOM для чтения из файла

//создаем объект, который будет экземпляром класса DomDocument
$dom = new DomDocument();

//Загружаем наш xml файл
$dom->load("catalog.xml");

//Так как в файле, в любом случае, есть корневой элемент,
//получаем первым делом именно его.
//Для этого используется свойство документа documentElement
$root = $dom->documentElement;

//Если запросить тип узла, который сейчас находится в root
//получим 1
echo $root->nodeType;

//Для получения списка/коллекции всех "детей"/дочерних узлов, корневого элемента
//используем свойство childNodes
//Дочерними узлами корневого элемента в нашем случае будут элементы book
$children = $root->childNodes;

//Для получения текстового контента используется свойство textContent
$textContent = $root->textContent;

//Для того, чтобы получить коллекцию элементов по их имени,
//используется метод getElementsByTagName("elementName")
$books = $dom->getElementsByTagName("book");

Чтение xml документа

<!-- содержание xml файла -->

<?xml version="1.0" encoding="UTF-8"?>

<catalog>

  <book>

    <title>Братья Карамазовы</title>

    <desc>Великая книга</desc>

    <price>1000</price>

</book>

 

  <book>

    <title>Страдания юного Вертера</title>

    <desc>Стоящая книга</desc>

    <price>100</price>

  </book>

</catalog>
<!-- Содержание php скрипта → $dom = new DomDocument(); $dom->load("catalog.xml");
$root = $dom->documentElement;
//
foreach($root->childNodes as $book){
    if($book->nodeType == 1){
        echo "";
            foreach($book->childNodes as $item){
                if($item->nodeType == 1){
                    echo "{$item->textContent}";
                }
            }
        echo "";
    }
}

Базовое использование DOM для создания/изменения документа

//===
//создаем объект, который будет экземпляром класса DomDocument
//Параметры передадут значения в пролог документа
//указав версию и кодировку
$dom = new DOMDocument("1.0", "utf-8");

//===
//Создаем элементы book и title
//НО данные методы не создают сразу элементы в файле,
//а лишь в памяти
$catalog = $dom->createElement("catalog");
$book = $dom->createElement("book");
$title = $dom->createElement("title");

//===
//По аналогичной схеме создаем в памяти
//текстовый узел
$bookName = $dom->createTextNode("php 7 в подлиннике");

//===
//теперь мы можем созданные узлы вложить друг в друга
$title->appendChild($bookName);
$book->appendChild($title);
$catalog->appendChild($book);

//===
/*PHP предоставляет дополнительный, упрощенный способ с созданием элементов*/
$author = $dom->createElement("author", "Игорь Симдянов и Дмитрий Котеров");

//===
//Также может возникнуть задача вставить узел не в конец,
//а, например, перед каким-то конкретным узлом
//вставим в узел book,
//элемент author перед элементом title
$book->insertBefore($author, $title);

//===
//При создании текстового узла,
//мы можем создавать такие узлы, которые
//содержат запрещенные символы.
//Используя для этого метод createCDATASection
$description = $dom->createElement("description");
$cdata_desc = $dom->createCDATASection(
    "В книге раскрыта древняя тайна использования символов < & >
    ");
$description->appendChild($cdata_desc);
$book->appendChild($description);

//===
//Далее элемент каталог мы вкладываем в тело документа
//он и будет корневым элементом
$dom->appendChild($catalog);

//===
//После того, как логика будет составлена остается
//только сохранить созданные узлы в документ
$dom->save("book_catalog.xml");

В результате описанных выше манипуляций, мы получим следующий xml документ.

<?xml version="1.0" encoding="utf-8"?>

<catalog>

  <book>

    <author>Игорь Симдянов и Дмитрий Котеров</author>

    <title>php 7 в подлиннике</title>

    <description><![CDATA[В книге раскрыта древняя тайна использования символов < & >

    ]]></description>

  </book>

</catalog>

Simple XML

Этот инструмент предназначен для чтения xml документа. Хотя, есть возможность и изменить текстовое содержимое элемента. Инструмент является надстройкой над DOM. Представляет собой более простой способ чтения.

Базовое использование

<!-- файл xml -->

<?xml version="1.0" encoding="UTF-8"?>

<catalog>

  <book>

    <title>Братья Карамазовы</title>

    <desc>Великая книга</desc>

    <price>1000</price>

  </book>

 

  <book>

    <title lang="ru">Страдания юного Вертера</title>

    <desc>Стоящая книга</desc>

    <price>100</price>

  </book>

</catalog>
<!-- файл php скрипта -->
//Для загрузки документа и преобразования его в объект 
//используется метод simplexml_load_file; 
$sxml = simplexml_load_file("catalog.xml"); 

/*Для тех случаев, когда нужно работать не с файлом, а с xml в виде строки, 
используется метод simplexml_load_ $sxml = simplexml_load_string("XML строка"); */
 
//как результат, в переменной $sxml будет объект, 
//свойствами которого стали все элементы, входящие в состав корневого. 
//Следовательно, чтобы получить текст элемента //используется следующий подход. 
//Для примера получим название второй книги из каталога echo $sxml->book[1]->title;
//Страдания юного Вертера

//Если нужно получить значение атрибута,
//используем аналогичную конструкцию
echo $sxml->book[1]->title["lang"];//ru

//По тому же принципу можно и заменить содержание элемента
//Сначала меняем его в памяти
$sxml->book[0]->title = "php 7 в подлиннике";

//Далее, мы берем все содержимое корневого элемента,
//преобразованное к строке
$xml = $sxml->asXML();

//и записываем все это в файл
file_put_contents("catalog.xml", $xml);

Преобразование XML с XSL/T

Не смотря на то, что для стилизации xml документов можно применять даже обычный css, так практически никто не делает. Для преобразования xml документа используется технология XSL/T, что значит — Extensible Stylesheet Language/Transformations.

Описание работы с XSL/T выходит за рамки этого урока, так как инструмент сложный и в несколько абзацев его не вместить. Как впрочем и CSS. Поэтому, данную тему я попытаюсь раскрыть подробнее, когда возьмусь ее за изучение.

Подключается файл xsl/t в блоке декларации следующим образом

<?xml-stylesheet type="text/xsl" href="file_name.xsl"?>

Это стандартный метод подключения. Тут подразумевается, что вы открываете в браузере xml, а в нем есть ссылка на преобразователь. Браузер загружает файл по этой ссылке и на его основе отрисовывает преобразованный xml. Php предоставляет возможность подключить преобразователь к xml документу на сервере. В результате, вы сможете обращаться к php скрипту, а получить преобразованный xml.

Используется для этого штатное расширение php.

Пример

//Создаем объект для xml
$xml = new DomDocument();

//Загружаем в этот объект xml документ
$xml->load("catalog.xml");

//Создаем объект для xsl
$xsl = new DomDocument();

//Загружаем в этот объект xsl документ
$xml->load("catalog.xsl");

//Создаем экземпляр класса XSLTProcessor
$processor = new XSLTProcessor();

//Загружаем xsl в процессор
$processor->importStylesheet($xsl);

//Преобразование переданного в процессор xml файла
//на основе имеющегося xsl
//И вывод на экран
echo $processor->transformToXML($xml);

Автор Виталий Сухомлинов
практикующий Seo-специалист
и программист любитель

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *