Статьи

Создание XML-документов в PHP

Существует множество причин, по которым вы хотите создавать XML-документы с использованием PHP. Возможно, вы пишете свой собственный канал RSS или внедряете сервис REST . Вне зависимости от причины, это руководство познакомит вас с объектом DOMDocument и его использованием для создания динамических XML-документов.

Прежде чем мы начнем создавать настоящий XML, нам нужно что-то сделать из него. Я собираюсь начать с объявления класса, который будет содержать некоторую информацию о последних уроках здесь в Switch On The Code. Мы возьмем коллекцию этих объектов и создадим тот же XML, который был проанализирован jQuery в предыдущем уроке.

class Tutorial
{
public $author;
public $title;
public $date;
public $categories;

function __construct(
$author, $title, $date, $categories)
{
$this->author = $author;
$this->title = $title;
$this->date = $date;
$this->categories = $categories;
}
}

Здесь у нас есть очень простой объект PHP, который содержит различную информацию об учебнике — автор, название, дату публикации и категории. Давайте заполним массив из четырех таких объектов, которые мы затем преобразуем в XML.

$tutorials = array(
new Tutorial(
"The Reddest",
"Silverlight and the Netflix API",
"1/13/2009",
array(
"Tutorials",
"Silverlight 2.0",
"Silverlight",
"C#",
"XAML"
)
),

new Tutorial(
"The Hairiest",
"Cake PHP 4 - Saving and Validating Data",
"1/12/2009",
array(
"Tutorials",
"CakePHP",
"PHP"
)
),

new Tutorial(
"The Tallest",
"Silverlight 2 - Using initParams",
"1/6/2009",
array(
"Tutorials",
"Silverlight 2.0",
"Silverlight",
"C#",
"HTML"
)
),

new Tutorial(
"The Fattest",
"Controlling iTunes with AutoHotkey",
"12/12/2008",
array(
"Tutorials",
"AutoHotkey",
)
)
);

Теперь мы находимся в самой сути учебника — на самом деле строим некоторый XML.

header("Content-Type: text/plain");

//create the xml document
$xmlDoc = new DOMDocument();

//create the root element
$root = $xmlDoc->appendChild(
$xmlDoc->createElement("RecentTutorials"));

//make the output pretty
$xmlDoc->formatOutput = true;

echo $xmlDoc->saveXML();

Первая строка просто говорит браузерам, что я не возвращаю HTML, я просто возвращаю простой текст. Это препятствует тому, чтобы они пытались представить наш XML как HTML, который обычно не работает и дает вам пустой экран. Затем я создаю экземпляр DOMDocument . Конструктор принимает необязательную версию и кодировку, но по умолчанию он равен «1.0», что мне подходит. Далее я создаю корневой узел, который в моем случае есть RecentTutorials. Я делаю это, создавая элемент с помощью функции createElement в DOMDocument и добавляя его как дочерний элемент в документ XML. Теперь я просто говорю DOMDocument отформатировать вывод, что делает его красивым, и отображать его на дисплее. Если мы запустим этот скрипт прямо сейчас, мы получим следующее:

<?xml version="1.0"?>
<RecentTutorials/>

Теперь давайте начнем заполнять наш XML информацией о руководствах. Мы начнем с простого создания Tutorialтега и отображения автора в качестве атрибута, а заголовка и даты — в качестве дочерних элементов.

foreach($tutorials as $tut)
{
//create a tutorial element
$tutTag = $root->appendChild(
$xmlDoc->createElement("Tutorial"));

//create the author attribute
$tutTag->appendChild(
$xmlDoc->createAttribute("author"))->appendChild(
$xmlDoc->createTextNode($tut->author));

//create the title element
$tutTag->appendChild(
$xmlDoc->createElement("Title", $tut->title));

//create the date element
$tutTag->appendChild(
$xmlDoc->createElement("Date", $tut->date));
}

Сначала я создаю тег для учебника так же, как и корневой тег, за исключением того, что теперь я добавил его в качестве дочернего элемента к корневому элементу вместо документа XML. К сожалению, в отличие от createElement, createAttributeне имеет возможности принять значение в конструкторе. Это означает, что мы должны использовать очень подробный синтаксис для добавления атрибута к элементу. Сначала мы вызываем createAttribute и передаем ему желаемое имя, затем мы должны добавить значение атрибута в качестве дочернего, вызвав createTextNode и передав ему значение. После того, как мы создали атрибут, мы просто добавляем его в качестве дочернего к тегу учебника. Наконец, мы добавляем элементы для заголовка и даты, вызывая createElement и передавая имена и значения. Теперь у нас есть что-то похожее на это:

<?xml version="1.0"?>
<RecentTutorials>
<Tutorial author="The Reddest">
<Title>Silverlight and the Netflix API</Title>
<Date>1/13/2009</Date>
</Tutorial>
<Tutorial author="The Hairiest">
<Title>Cake PHP 4 - Saving and Validating Data</Title>
<Date>1/12/2009</Date>
</Tutorial>
<Tutorial author="The Tallest">
<Title>Silverlight 2 - Using initParams</Title>
<Date>1/6/2009</Date>
</Tutorial>
<Tutorial author="The Fattest">
<Title>Controlling iTunes with AutoHotkey</Title>
<Date>12/12/2008</Date>
</Tutorial>
</RecentTutorials>

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

//create the categories element
$catTag = $tutTag->appendChild(
$xmlDoc->createElement("Categories"));

//create a category element for each category in the array
foreach($tut->categories as $cat)
{
$catTag->appendChild(
$xmlDoc->createElement("Category", $cat));
}

И там у вас есть это. Теперь у нас есть полный XML-документ.

<?xml version="1.0"?>
<RecentTutorials>
<Tutorial author="The Reddest">
<Title>Silverlight and the Netflix API</Title>
<Date>1/13/2009</Date>
<Categories>
<Category>Tutorials</Category>
<Category>Silverlight 2.0</Category>
<Category>Silverlight</Category>
<Category>C#</Category>
<Category>XAML</Category>
</Categories>
</Tutorial>
<Tutorial author="The Hairiest">
<Title>Cake PHP 4 - Saving and Validating Data</Title>
<Date>1/12/2009</Date>
<Categories>
<Category>Tutorials</Category>
<Category>CakePHP</Category>
<Category>PHP</Category>
</Categories>
</Tutorial>
<Tutorial author="The Tallest">
<Title>Silverlight 2 - Using initParams</Title>
<Date>1/6/2009</Date>
<Categories>
<Category>Tutorials</Category>
<Category>Silverlight 2.0</Category>
<Category>Silverlight</Category>
<Category>C#</Category>
<Category>HTML</Category>
</Categories>
</Tutorial>
<Tutorial author="The Fattest">
<Title>Controlling iTunes with AutoHotkey</Title>
<Date>12/12/2008</Date>
<Categories>
<Category>Tutorials</Category>
<Category>AutoHotkey</Category>
</Categories>
</Tutorial>
</RecentTutorials>

И так, чтобы вы могли видеть все в одном месте, вот окончательное содержание скрипта PHP:

class Tutorial
{
public $author;
public $title;
public $date;
public $categories;

function __construct(
$author, $title, $date, $categories)
{
$this->author = $author;
$this->title = $title;
$this->date = $date;
$this->categories = $categories;
}
}

//make some tutorial objects
$tutorials = array(
new Tutorial(
"The Reddest",
"Silverlight and the Netflix API",
"1/13/2009",
array(
"Tutorials",
"Silverlight 2.0",
"Silverlight",
"C#",
"XAML"
)
),

new Tutorial(
"The Hairiest",
"Cake PHP 4 - Saving and Validating Data",
"1/12/2009",
array(
"Tutorials",
"CakePHP",
"PHP"
)
),

new Tutorial(
"The Tallest",
"Silverlight 2 - Using initParams",
"1/6/2009",
array(
"Tutorials",
"Silverlight 2.0",
"Silverlight",
"C#",
"HTML"
)
),

new Tutorial(
"The Fattest",
"Controlling iTunes with AutoHotkey",
"12/12/2008",
array(
"Tutorials",
"AutoHotkey",
)
)
);

//create the xml document
$xmlDoc = new DOMDocument();

//create the root element
$root = $xmlDoc->appendChild(
$xmlDoc->createElement("RecentTutorials"));


foreach($tutorials as $tut)
{
//create a tutorial element
$tutTag = $root->appendChild(
$xmlDoc->createElement("Tutorial"));

//create the author attribute
$tutTag->appendChild(
$xmlDoc->createAttribute("author"))->appendChild(
$xmlDoc->createTextNode($tut->author));

//create the title element
$tutTag->appendChild(
$xmlDoc->createElement("Title", $tut->title));

//create the date element
$tutTag->appendChild(
$xmlDoc->createElement("Date", $tut->date));

//create the categories element
$catTag = $tutTag->appendChild(
$xmlDoc->createElement("Categories"));

//create a category element for each category in the array
foreach($tut->categories as $cat)
{
$catTag->appendChild(
$xmlDoc->createElement("Category", $cat));
}
}

header("Content-Type: text/plain");

//make the output pretty
$xmlDoc->formatOutput = true;

echo $xmlDoc->saveXML();

В целом, процесс создания XML-документов в PHP кажется мне довольно многословным, особенно по сравнению с использованием объекта .NET XDocument . Помимо этого, он все еще очень простой, мощный и, безусловно, выполняет свою работу.