SimpleXML. Начало работы

24.04.2013

Теги: PHPWeb-разработкаXML

Расширение SimpleXML предоставляет очень простой и легкий в использовании набор инструментов для преобразования XML в объект, с которым можно затем работать через его свойства и с помощью итераторов. SimpleXML присутствует в PHP начиная с версии 5.

Для наглядности, в качестве примера будем использовать XML, описывающий простой кулинарный рецепт, взятый с википедии.

<?xml version="1.0" encoding="UTF-8"?>
<recipe name="хлеб" preptime="5" cooktime="180">
  <title>Простой хлеб</title>
  <ingredient amount="3" unit="стакан">Мука</ingredient>
  <ingredient amount="0.25" unit="грамм">Дрожжи</ingredient>
  <ingredient amount="1.5" unit="стакан">Тёплая вода</ingredient>
  <ingredient amount="1" unit="чайная ложка">Соль</ingredient>
  <instructions>
   <step>Смешать все ингредиенты и тщательно замесить.</step>
   <step>Закрыть тканью и оставить на один час в тёплом помещении.</step>
   <step>Замесить ещё раз, положить на противень и поставить в духовку.</step>
  </instructions>
</recipe>

Загрузка XML

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

$xml = simplexml_load_file('recipe.xml');
print_r($xml);
SimpleXMLElement Object
(
  [@attributes] => Array
      (
          [name] => хлеб
          [preptime] => 5
          [cooktime] => 180
      )
  [title] => Простой хлеб
  [ingredient] => Array
      (
          [0] => Мука
          [1] => Дрожжи
          [2] => Тёплая вода
          [3] => Соль
      )
  [instructions] => SimpleXMLElement Object
      (
          [step] => Array
              (
                  [0] => Смешать все ингредиенты и тщательно замесить.
                  [1] => Закрыть тканью и оставить на один час в тёплом помещении.
                  [2] => Замесить ещё раз, положить на противень и поставить в духовку.
              )
      )
)

Кроме того, существует еще и функция simplexml_load_string(), которая берет XML не из файла, а из строки.

$str = file_get_contents('recipe.xml');
$xml = simplexml_load_string($str);

Получение данных

SimpleXML предоставляет очень удобный способ получения данных из XML. К примеру, для того чтобы получить какой-либо узел документа достаточно просто обратится к этому узлу по имени:

// Выводит содержимое элемента <title>
echo $xml->title;

Поскольку ингредиентов у нас несколько, то $xml->ingredient будет массивом из четырех элементов. Перебрать все ингредиенты можно так:

foreach ( $xml->ingredient as $ingredient ) {
    echo $ingredient . '<br/>';
}

Для того что бы получить, к примеру, третий ингредиент (теплая вода), достаточно обратиться к нему по индексу:

$xml->ingredient[2]; // элементы массивы нумеруются с нуля

Шаги приготовления (step) являются дочерними для элемента instructions, чтобы получить их, нужно сначала получить instructions:

echo $xml->instructions->step; // выводит текст первого шага

Атрибуты

Работать с атрибутами тоже очень легко. Они доступны как ассоциативный массив своего элемента. То есть, для того что бы получить название рецепта (атрибут name корневого узла recipe), достаточно написать:

echo $xml['name'];

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

echo $xml->ingredient['amount'];

Сейчас мы рассмотрели только один способ получения данных: когда нам уже известны названия узлов и атрибутов. Но случается и так, когда структура XML файла заранее не известна, но нам нужно его обработать. SimpleXML предоставляет и такую возможность.

Получение дочерних узлов

Метод children() возвращает список дочерних элементов. В нашем случае $xml — корневая ветвь, и если написать:

$nodes = $xml->children();
echo $nodes[0];

то получим содержимое элемента <title>, а если:

$nodes = $xml->children();
echo $nodes[2];

то второй ингредиент.

Обойти все дочерние ветви первого уровня легко можно при помощи цикла foreach:

echo '<ul>';
foreach ( $xml->children() as $node ) {
    if ( count($node) == 0 ) echo '<li>' . $node . '</li>';
}
echo '</ul>';

Результат:

<ul>
  <li>Простой хлеб</li>
  <li>Мука</li>
  <li>Дрожжи</li>
  <li>Тёплая вода</li>
  <li>Соль</li>
</ul>

Фукция count() позволяет определить количество дочерних узлов.

Для того, чтобы получить имя текущий ветви, используется метод getName():

$nodes = $xml->children();
echo $nodes[0]->getName(); // выведет title

Получение атрибутов

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

$nodes = $xml->children();
// все атрибуты узла <ingredient>Мука</ingredient>
foreach ( $nodes[1]->attributes() as $name => $value ) {
    echo 'атрибут ' . $name . ', значение ' . $value . '<br/>';
}

Результат:

атрибут amount, значение 3<br/>
атрибут unit, значение стакан<br/>

Изменение значений узлов и атрибутов

Объект SimpleXMLElement позволяет манипулировать всеми элементами:

$xml = simplexml_load_file('recipe.xml');
$xml->title = 'Ржаной хлеб';
$xml->ingredient[0] = 'Ржаная мука';
print_r($xml);
$xml->ingredient[2]['amount'] = '300';
$xml->ingredient[2]['unit'] = 'грамм';
print_r($xml->ingredient[2]);

Результат:

SimpleXMLElement Object
(
  [@attributes] => Array
      (
          [name] => хлеб
          [preptime] => 5
          [cooktime] => 180
      )
  [title] => Ржаной хлеб
  [ingredient] => Array
      (
          [0] => Ржаная мука
          [1] => Дрожжи
          [2] => Тёплая вода
          [3] => Соль
      )
  [instructions] => SimpleXMLElement Object
      (
          [step] => Array
              (
                  [0] => Смешать все ингредиенты и тщательно замесить.
                  [1] => Закрыть тканью и оставить на один час в тёплом помещении.
                  [2] => Замесить ещё раз, положить на противень и поставить в духовку.
              )
      )
)
SimpleXMLElement Object
(
    [@attributes] => Array
        (
            [amount] => 300
            [unit] => грамм
        )

    [0] => Тёплая вода
)

Добавление элементов и атрибутов

Чтобы добавить дочерний элемент к текущему, достаточно использовать метод addChild(). Первым параметром идет имя нового элемента, вторым значение, которое задавать необязательно.

Добавим еще один шаг к инструкциям:

$node = $xml->instructions; // получаем ветвь инструкций
$node->addChild('step', 'Почитать газету'); // добавляем элемент
print_r($node);

Результат:

SimpleXMLElement Object
(
    [step] => Array
        (
            [0] => Смешать все ингредиенты и тщательно замесить.
            [1] => Закрыть тканью и оставить на один час в тёплом помещении.
            [2] => Замесить ещё раз, положить на противень и поставить в духовку.
            [3] => Почитать газету
        )

)

Метод addAttribute() позволяет добавить атрибут к текущему узлу. Первый параметр это имя атрибута, второй значение.

$node = $xml->instructions; // получаем ветвь инструкций
$step = $node->addChild('step', 'Почитать газету'); // добавляем элемент
$step->addAttribute('newspaper', 'Аргументы и факты'); // добавляем артибут
print_r($step);

Результат:

SimpleXMLElement Object
(
    [@attributes] => Array
        (
            [newspaper] => Аргументы и факты
        )

    [0] => Почитать газету
)

Использование XPath

SimpleXML включает в себя встроенную поддержку XPath. Поиск всех элементов <step>:

foreach ($xml->xpath('//step') as $step) {
    echo $step . '<br/>';
}

Результат:

Смешать все ингредиенты и тщательно замесить.<br/>
Закрыть тканью и оставить на один час в тёплом помещении.<br/>
Замесить ещё раз, положить на противень и поставить в духовку.<br/>

Взаимодействие с DOM

PHP может преобразовывать XML узлы из SimpleXML в формат DOM и наоборот. Этот пример показывает, как можно изменить DOM элемент в SimpleXML:

$dom = new DOMDocument('1.0', 'utf-8');
$dom->load('recipe.xml');
$xml = simplexml_import_dom($dom);

Дополнительная информация

Поиск: PHP • Web-разработка • XML

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.