Снова парсинг: SimpleXML

Я уже останавливался на теме парсинга XML-файлов в статье Как я научился парсить XML в PHP. Сегодня я обнаружил, что есть способ вытаскивать данные из XML гораздо более приятный и менее подверженный ошибкам. Способ этот основан на использовании расширения SimpleXML, которое доступно в PHP начиная с версии 5.

Вообще, Вы наверно заметили, что я в последних статьях касаюсь только версии 5, не рассматривая при этом более старые версии. Но на то они и старые, чтобы их не рассматривать :) Сейчас практически все хостинги поддерживают версию 5 интерпретатора пхп.

Итак. Будем рассматривать, что же это за расширение такое - SimpleXML. Оказывается, вытащить данные из XML теперь проще простого. Например, у нас есть файл со следующей структурой, описывающей книгу:

books.xml

<!--?xml version=’1.0’ ?-->

Имя и фамилия автора

Количество страниц     ISBN
Год издания

Так вот, чтоб вытащить например все книги из этого хранилища, нам достаточно превратить этот файл в объект с помощью simplexml_load_file и перечислить элементы book:

getbooks.php

<!--?<br /--> $xml = simplexml_load_file(‘books.xml’);
foreach ($xml-&gt;book as $book) {
$book-&gt;title;  // извлекаем название книги
$book-&gt;author; // извлекаем имя и фамилию автора

}
?&gt;

Правда красиво? А главное - легко!

Кстати замечу, что если у нас есть содержимое xml в памяти (переменной), а не на диске (в файле), то можно использовать simplexml_load_string:

getbooks2.php

<!--?<br /--> // так мы присвоим переменной $xml_content содержимое документа
$xml_content = &lt;&lt; <!--?xml version=1.0’ ?-->

Имя и фамилия автора

Количество страниц       ISBN
Год издания

XML;

$xml = simplexml_load_string($xml_content);
foreach ($xml-&gt;book as $book) {
$book-&gt;title;  // извлекаем название книги
$book-&gt;author; // извлекаем имя и фамилию автора

}
?&gt;

Заметили, как я тут применил еще одну возможность php для объясления строковых переменных? Конечно заметили! Строку можно объявлять и без кавычек, но для этого ее нужно обрамлять строками

<<<[ИДЕНТИФИКАТОР]
[строка]
[ИДЕНТИФИКАТОР];

Между <<< и [ИДЕНТИФИКАТОР] не должно быть пробелов.

Ну это конечно к статье не относится. Я так, кстати заметил просто.

Вооот, теперь мы знаем, как легче можно извлечь информацию из xml-документов. Кстати, SimpleXML умеет работать с языком запросов XPath, который тоже используется для извлечения информации из XML-документа, но на этом я остановлюсь в отдельной статье.





Читайте также:



41 Ответов на “Снова парсинг: SimpleXML”

  1. гут, тоже закинул на социалку

  2. Было бы интересно узнать поподробнее

  3. novice

    Что именно Вы бы хотели узнать поподробнее?

  4. Cooler

    2 novice:
    ничего он не хотел узнавать, только проспамить свой сайт =)

    SimpleXML глючный с ним надо поосторожнее. Имхо DOMDocument + XPath практичнее.

  5. Александр

    Не подскажете, как перевести из объекта SimpleXML в строку?

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

  6. novice

    Не знаю, как выглядит Ваш код, Александр. Но я бы вытаскивал атрибуты из элемента вот так:

    <?
    $xml_content = <<<XML
    <?xml version='1.0' ?>
      <books>
        <book title="Title">
          <author>Author</author>
          <pages>Pages</pages>
          <isbn>ISBN</isbn>
          <year>Year</year>
        </book>
      </books>
    XML
    ;

      $xml = simplexml_load_string($xml_content);
      foreach ($xml->book as $book) {
        echo (string)$book['title']; // вернет Title
      }
    ?>

    Т.е. я тут использую явное преобразование типов с помощью (string). Хотя у меня и без этого строка, а не объект.

  7. Mitya

    Спасибо. Для новичков самое то=)

  8. Mitya

    Комменты в 9.5 опере не работают у Вас.

  9. novice

    Спасибо за замечание. В ближайшее время исправим. :)

  10. Нет все таки работают, только не очень удобно подается информация о том, что коммент ушел на модерирование. Точнее этой информации просто нет. Поэтому и кажется, что не работают=))

  11. novice

    Согласен. В плане удобства тут есть еще над чем поработать. :) Будем думать.

  12. Спасибо за пост!

  13. novice

    Незачто!

  14. Проблема с SimpleXML не в том, что он глючный, а в том, что он не предоставляет некоторых специфичных возможностей, с которыми легко справляется DOM.

    Например попробуйте добавить секцию CDATA в документ. Да и добавлять потомков в документ стало возможным, только с версии PHP 5.1.4.

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

  15. novice

    Мне все-таки кажется, что SimpleXml неходится немного в другой нише, нежели DOM. SimpleXML позиционирует себя так :
    “The SimpleXML extension provides a very simple and easily usable toolset to convert XML to an object that can be processed with normal property selectors and array iterators.” Другими словами его задача заключается только в том, чтобы преобразовать xml в объектную модель, а работой с этой моделью занимается уже другой инструмент. Поэтому я бы не стал называть отсутствие некоторых функций проблемой этого пакета :)

  16. Позиционирование - позиционированием, но когда доходит до практики, некоторые мелочи здорово портят жизнь. Получается…для считывания SimpleXML, для больших документов SAX, для манипулирования почти всем DOM. Не слишком ли получается много инструментов? Но это так ворчание. В целом я с Вами согласен.

    PS: А почему не работают извещения о комментариях? Снова найти Ваш сайт мне помог только Google Analytics.

  17. novice

    Никогда не пользовался этой функцией сам - не обратил внимания, что на нашем блоге ее нет 😉 В ближайшее время исправим.

  18. Спс большое -
    реально мне ща очень нужно про парсить XML файл - и скок не смотрел ничего не понимал.
    А вот SimpleXML это вещь !!!

    Спс еще раз.

  19. Информация про парсинг XML помогла уяснить некоторые моменты. Спасибо :)

    А вот про такое объявление строковых переменных вижу впервые… Думаю в некоторых случаях будет очень удобно применять.

  20. Неудивительно, что у вас посещаемость растет :), столько полезной (и самое главное, хорошо поданной) информации давно не встречал. Причем посты точь-в-точь совпадают с моими пробелами в знаниях!
    p.s.: получайте нового подписчика! Только почините RSS - у меня выдает “HTTP Error Code: 500″

  21. mat85

    А что делать если теги в XML русские?

    Милавица
    Классика…

  22. novice

    Честно говоря, не пробовал русские теги читать) попробуйте

  23. mat85

    В том то и дело, что я пробовал, но не получается, так как на прямую не укажешь foreach $xml->номенклатура as $book), а очень часто нужно обработать выгрузку из 1С, которая бывает на русском. Но вообще сайт супер. Большого Вам развития

  24. Не подскажите как с помощью SimpleXML получит доступ к url в такой конструкции?

    <enclosure url=”https://www.test.ru/22/32/223292.jpg” type=”image/jpeg” length=”31644″ />

  25. novice

    Дмитрий, если Вам нужно обратиться к атрибуту тэга, смотрите мой комментарий Выше - с примером обращения к атрибуту title.

  26. С русскими тегами попробуйте вот так:

    foreach $xml->{‘номенклатура’} as $book

  27. Сергей

    Весь день пытался найти статью о том, как при помощи SimpleXML
    удалять(!) записи. К примеру в файле XML:

    Сережа
    про Сережу
    avapic_id1.jpg
    @mail.ru

    Коля
    про Колю
    avapic_id2.jpg
    @mail.ru

    две записи с атрибутами id=1 и id=2. Как определять и находить
    нужную запись я знаю. Но надо например удалить запись с аттрибутом
    id=2. Подскажите хотя бы принцип и операторы. Обязательно на SimpleXML
    Спасибо!

  28. novice

    Похоже, что в SimpleXML нет механизма редактирования/удаления элементов, но попробуйте почитать мою статью про редактирование: https://i-novice.net/izmenyaem-soderzhimoe-xml/. Возможно на ее основе Вы сможете реализовать удаление.

  29. Сергей

    Забавно) на базе этой статьи я как раз и смог сделать добавление и редактирование уже существующих записей. Все работает. Конечно, в случае, если XML “разрастется”, то процесс обработки станет долговременным. Тут уже надо прибегать к другим средствам, МуСКЛ, к примеру. С ними то все просто. Но не хочется создавать целую базу ради, скажем, 10 пользователей). А система DOM или XPath, у меня отказываются работать. Потому и пришлось остановиться именно на SimpleXML. На базе вышеназванных движков очень много статей о редактировании или удалении/добавлении записей в XML. Может еще какие-нить мысли?

  30. Сергей

    Итак, проломав голову еще пару дней пришел вот к чему:
    Имеем XML вида:

    Василий пупкин
    про Васю пупкина
    avapic_id0.jpg
    @mail.ru

    Петя
    про Пети
    avapic_id1.jpg
    @mail.ru

    Сережа
    про Сережу
    avapic_id2.jpg
    @mail.ru

    Саша
    примечание
    avapic_id3.jpg
    саша@mail.ru

    А вот код PHP, который позволяет удалить пользователя по аттрибуту id:
    function delete_auth_xml ($id){
    $xmlpath = “../authors.xml”;
    $xml = @simplexml_load_file($xmlpath) or die (“База данных не может быть загружена”) ;
    $count = 0;
    foreach ($xml->authorinfo as $authorinfo){
    if ($id == $authorinfo[‘id’]) {
    unset($xml->authorinfo[$count]); break;
    }
    $count++;
    };
    $xml->asXML($xmlpath);
    };

    параметр функции $id - значение аттрибута id из XML. При желании можно поставить запрос на выполнение на JavaScript’е.

  31. Сергей

    Уважаемый админ этого сервиса, сделайте, чтоб XML отображались как надо в комментах))

  32. Юрий

    Покажите пожалуйста как применить xpath к выбраному узлу. Например.

    я выбрал товары

    foreach ($xml->xpath(‘//Товар/’) as $product) {
    print_r($product)
    }

    теперь я хочу каждый найденый товар распарсить на характеристики

    Пишу так.

    foreach ($xml->xpath(‘//Товар/’) as $product) {
    foreach ($product->xpath(‘/Вес’) as $weight) {
    print_r($weight)
    }
    }

    Не получается ((

  33. Bob Kelso

    Все бы ничего, но на данном этапе не могу получить в переменную значение атрибута, если имя атрибута содержит “-” (дефис).
    например:

    Али-Сахид
    252

    через XML могу найти зарплату ($xml->worker->salary)
    но не могу найти имя ($xml->worker->name не дает ничего). Такое ощущение, что дефисные имена атрибутов вводят simpleXML в ступор

  34. Люди киньте ссылку как парсить смешанные элементы, т.е. XML у меня такой:
    ..
    S_191513
    1381326
    20081218
    1001500110015001

    Спасибо

  35. Спасибо за статью! Очень пригодилась в данную минуту быстро решить не сложную задачу. Единственный вопрос как он работает с большими объемами xml-данных в несколько сотен мегабайт?

  36. novice

    Проверьте, самому интересно 😉

  37. Diam

    Ребят, а как получить имя тега?

  38. SimpleXML

    Есть ли возможность использовать SimpleXML, если у хостера не включена данная функция? Как?

  39. уважаемый админ. мне нужно извлекать узлы в массив переменных. вот кусок xml

    8741258

    87412329

    меня пугает вложенность. какая команда извлечёт узлы с такой вложенностью? может быть в simpleXML есть стандартное решение?
    из массива мне нужен первый элемент и количество элементов.

  40. ohoho

    Наверное, вы и есть мой спаситель. Пожалуйста, помогите!
    Есть файл новостей news.xml

    ***

    полная новость

    ***

    полная новость 2

    Короткие новости выводятся на главной странице, а полные c xml “тянутся” на news.php. Можно ли присвоить id каждой новости, чтобы при клике по новости короткой отображалась длинная, а не тексты всех новостей одновременно?
    СПАСИБО.

  41. ohoho

    Наверное, вы и есть мой спаситель. Пожалуйста, помогите!
    Есть файл новостей news.xml

    ***

    полная новость

    ***

    полная новость 2

    Короткие новости выводятся на главной странице, а полные c xml “тянутся” на news.php по ссылке “подробнее”. Можно ли присвоить id каждой новости, чтобы при клике по новости короткой отображалась длинная, а не тексты всех новостей всем списком одновременно?
    СПАСИБО.


© Copyright. . I-Novice. All Rights Reserved. Terms | Site Map