Jump to content

Волчьи заметки

Sign in to follow this  
  • entries
    57
  • comments
    9
  • views
    64439

Получение данных XML без начального узла

Belkir

594 views

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

Пример XML кода

<?xml version="1.0" encoding="utf-8"?><root>   <first>1</first>   <second/>   <last>3</last></root>

Стандартным решением будет воспользоваться xPath и получить в ответ объект SimpleXmlElement содержащий в себе узел, на который указывает ссылка

<?php$xml = simplexml_load_string(   '<?xml version="1.0" encoding="utf-8"?>   <root>      some text      <first>1</first>	  <second/>	  <last>3</last>   </root>',   'SimpleXMLElement',   LIBXML_COMPACT);echo $xml -> xpath ( '/root' ) -> asXml ();?>

Но есть пара проблем: данная реализация вернет вам не только содержимое узла "root", но и сам узел "root", а так же, заголовок кода, указывающий на признак xml

<?xml version="1.0" encoding="utf-8"?><root>   some text   <first>1</first>   <second/>   <last>3</last></root>

Мы же хотим получить только содержимое узла "root"

some text<first>1</first><second/><last>3</last>

Есть костыльный, составной вариант

<?php$data = $xml -> xpath ( '/root' ) -> asXml ();preg_match('|<root>(.+?)</<root>|isuU', $data, $data);echo $data;?>

Этот подход работает, но имеет много минусов:

  • Требуется знать имя корневого узла
  • Вместо оперирования удобными объектами SimleXmlElement, нам приходится возиться с текстовыми строками (что добавит проблем при попытке компоновки полученной строки с другим xml кодом)
  • Использование ресурсоемких регулярных выражений

Я же, решая свои задачи, нашел более удобный и практичный способ, который позволяет избежать перечисленных выше проблем

<?php$data = $xml -> xpath ( '/root' );$dataChildren = array ();foreach(   $data -> children ()   as   $child){   $dataChildren [] = $child;}$data = array_merge(   array ( strval ( $data ) ),   $dataChildren);// Пример вывода данныхforeach(   $data   as   $element){   if ( is_string ( $element ) )   {      echo $element;   }   else   {      echo $element -> asXml ();   }}?>

Что же тут происходит? А вот что:

  1. Мы получаем объект SimpleXmlElement с узлом "root"
  2. Перебираем его потомков и каждого добавляем в массив (коллекцию)
  3. Добавляем в коллекцию строковое представление корневого узла (это необходимо чтобы кроме дочерних узлов в результат попал и текст корневого узла "some string"; к слову говоря - children () возвращает объект-массив узлов, но не текстового содержимого, а если преобразовать узел к строчному представлению - мы получим только текстовое содержимое узла)
  4. Полученный массив (коллекция) включает в себя текстовое содержимое необходимого узла + все его дочерние узлы с их полным содержимым
  5. Далее мы можем оперировать с массивом как того пожелаем

Этот подход более громоздок в реализации, но позволяет не терять удобный для работы формат объектов XML и отбрасывать различный мусор вроде имени самого узла или признака XML кода.



0 Comments


Recommended Comments

There are no comments to display.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×