Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SimpleXML, серриализация 
V
    Опции темы
Sergey89
Дата 5.9.2007, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



Код

<?php
$xml_str = <<<XML
<?xml version="1.0"?>
<parent>
    <child1>Hello!</child1>
    <child2></child2>
    <child3 />
</parent>
XML;

$xml = new SimpleXMLElement($xml_str);
$xml = (array)$xml;
unserialize(serialize($xml));

Код

SimpleXMLElement Object
(
    [child1] => Hello!
    [child2] => SimpleXMLElement Object
        (
        )

)

Код

O:16:"SimpleXMLElement":2:{s:6:"child1";s:6:"Hello!";s:6:"child3";O:16:"SimpleXMLElement":0:{}}


Суть проблемы в том, что пустые узлы не рассериализовать. Натыкаемся на предупреждение:
Код

Warning: unserialize() [function.unserialize]: Node no longer exists


Одно решение я нашёл:
Код
<?php
$xml = (array)$xml;

foreach ($xml as &$node) {
   if ($node instanceof SimpleXMLElement) {
      $node = null;
   }
}


Но может есть что-то более изящное?
--------------------
mlib.com.ru
PM MAIL   Вверх
WolfON
Дата 5.9.2007, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 1
Всего: 8



Нет - изящного выхода отсюда нету.

Может быть имеет смысл пересмотреть структуру xml, может-быть сделать child3 атрибутом, если он имеет какой-то смысл.
А если не имеет, то зачем его хранить? можно добавить когда потребуется.
PM MAIL ICQ   Вверх
Sergey89
Дата 5.9.2007, 19:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



WolfON, имеется уже готовый XML файл. Хочется всячески исключить правку самого файла, т.к. он находится в ZIP архиве.
--------------------
mlib.com.ru
PM MAIL   Вверх
WolfON
Дата 5.9.2007, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 1
Всего: 8



Тогда обойдитесь без сериализации а сохраняйте все в xml.
Что мешает?
PM MAIL ICQ   Вверх
Sergey89
Дата 5.9.2007, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



WolfON, этот XML файл разбирается скриптом и результат записывается в массив. Чтобы повторно не разбирать XML, сделано кэширование массива через серриализацию.
--------------------
mlib.com.ru
PM MAIL   Вверх
WolfON
Дата 5.9.2007, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 1
Всего: 8



ну тогда остается только ваш первый вариант
PM MAIL ICQ   Вверх
Sergey89
Дата 5.9.2007, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



Пришла в голову ещё одна идея
Код

<?php
$xml_str = <<<XML
<?xml version="1.0"?>
<parent>
    <child1>Hello!</child1>
    <child2></child2>
    <child3 />
</parent>
XML;

$xml = new SimpleXMLElement($xml_str);
$str = str_replace('O:16:"SimpleXMLElement":0:{}', 's:0:"";', serialize((array)$xml));

print_r(unserialize($str));

--------------------
mlib.com.ru
PM MAIL   Вверх
Diesel Draft
Дата 6.9.2007, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 876
Регистрация: 18.1.2005
Где: Lviv, Ukraine

Репутация: нет
Всего: 5



Я б написал класс, который создает точно такую структуру, а потом серелезирувал


--------------------
НЕДОМА в маси 
PM MAIL WWW ICQ GTalk   Вверх
Sergey89
Дата 6.9.2007, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



Diesel Draft, предлагаешь велосипед изобрести и написать программную реализацию SimpleXML? Хотя можно с наследованием от SimpleXML чё-нить замутить.
--------------------
mlib.com.ru
PM MAIL   Вверх
WolfON
Дата 6.9.2007, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 1
Всего: 8



Уффф... я вот не понимаю - вам нужно уменьшение нагрузки или что?
Решение с циклом самое быстрое.
PM MAIL ICQ   Вверх
Diesel Draft
Дата 6.9.2007, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 876
Регистрация: 18.1.2005
Где: Lviv, Ukraine

Репутация: нет
Всего: 5



Sergey89, Насчет наследования. Я пишу объект который наследует SimpleXML. Но припустим на сервере нет SimpleXML тогда я заменяю класс, не меняя имени на другой. Этот класс умеет все то самое, но реализован на РНР


--------------------
НЕДОМА в маси 
PM MAIL WWW ICQ GTalk   Вверх
Sergey89
Дата 6.9.2007, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



Цитата(WolfON @  6.9.2007,  17:04 Найти цитируемый пост)
Уффф... я вот не понимаю - вам нужно уменьшение нагрузки или что?
Решение с циклом самое быстрое. 

Отвлекитесь от кэширования и всего прочего. Я сейчас поставил вопрос конкретно о проблеме серриализации SimpleXML объекта. Но вот решение c str_replace всёравно быстрее.

Цитата(Diesel Draft @  6.9.2007,  17:37 Найти цитируемый пост)
Sergey89, Насчет наследования. Я пишу объект который наследует SimpleXML. Но припустим на сервере нет SimpleXML тогда я заменяю класс, не меняя имени на другой. Этот класс умеет все то самое, но реализован на РНР 

Хостинг без поддержки SimpleXML - недохостинг. PHP 4 сдыхает, а на PHP 5 перешёл любой дорожащий клиентами хостер. Но это так... лирическое отступление.
--------------------
mlib.com.ru
PM MAIL   Вверх
WolfON
Дата 6.9.2007, 19:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 1
Всего: 8



Цитата

Хостинг без поддержки SimpleXML - недохостинг. PHP 4 сдыхает, а на PHP 5 перешёл любой дорожащий клиентами хостер. Но это так... лирическое отступление.

XML у которого имеют смысл пустые элементы - недоxml smile
ну честно - грамотное использование технологии решит проблему сейчас и не возникнет много проблем в дальнейшем.
PM MAIL ICQ   Вверх
Sergey89
Дата 6.9.2007, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



WolfON, ну не совсем. Логично, конечно, будет писать <child2 />, но <child2></child2> также имеет право на жизнь.
--------------------
mlib.com.ru
PM MAIL   Вверх
Diesel Draft
Дата 7.9.2007, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 876
Регистрация: 18.1.2005
Где: Lviv, Ukraine

Репутация: нет
Всего: 5



Sergey89, что тема уже решена?


--------------------
НЕДОМА в маси 
PM MAIL WWW ICQ GTalk   Вверх
Sergey89
Дата 7.9.2007, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



Код

<?php
$str = <<<XML
<?xml version="1.0"?>
<root>
    <child1>Hello</child1>
    <child2></child2>
    <child3 />
    <child4>
        <child5></child5>
        <child6>World!</child6>
        <child7><child8 /></child7>
    </child4>
</root>
XML;

function xmlToArray($xml) {
    $xml = (array)$xml;

    foreach ($xml as &$v) {
        if (count($v) && ($v instanceof SimpleXMLElement)) {
            $v = xmlToArray((array)$v);
        } elseif ($v instanceof SimpleXMLElement) {
            $v = null;
        }
    }

    return $xml;
}

$xml = new SimpleXMLElement($str);
print_r(xmlToArray($xml));

С наследованием от SimpleXMLElemtnt ничего не вышло, т.к. конструктор базового класса объявлен как final.

ЗЫ мне кажется, или heredoc ситнаксис действительно не воспринимается как строка? Это я про подсветку кода.

Это сообщение отредактировал(а) Sergey89 - 7.9.2007, 23:15
--------------------
mlib.com.ru
PM MAIL   Вверх
WolfON
Дата 7.9.2007, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 1
Всего: 8



кажется - heredoc это по сути обычный комментарий
PM MAIL ICQ   Вверх
Sergey89
Дата 7.9.2007, 23:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



Нет. Это именно один из способов определения строки. http://php.net/heredoc
--------------------
mlib.com.ru
PM MAIL   Вверх
WolfON
Дата 7.9.2007, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 604
Регистрация: 19.7.2004

Репутация: 1
Всего: 8



черт попутал с phpdoc %)
PM MAIL ICQ   Вверх
Endeveit
Дата 8.9.2007, 20:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 2.6.2006

Репутация: 1
Всего: 7



ПХП не поддерживает десериализацию объектов DOM, SimpleXML и некоторых других (подробнее где-то на bugs.php.net)
В принципе возможно вот такое решение:
Код

<?php
class mySimpleXMLElement implements Serializable
{
    private $obj_instance = null;
    private $xml_instance = '';

    public function __construct($data)
    {
        $this->obj_instance = simplexml_load_string($data);
    }

    public function getInstance()
    {
        return $this->obj_instance;
    }

    public function serialize()
    {
        $this->xml_instance = $this->obj_instance->asXML();
        unset($this->obj_instance);
        return serialize($this->xml_instance);
    }

    public function unserialize($serialized)
    {
        $this->obj_instance = simplexml_load_string(unserialize($serialized));
    }
}

$xml_str = <<<XML
<?xml version="1.0"?>
 <parent>
  <child1>Hello!</child1>
  <child2></child2>
  <child3 />
</parent>
XML;

$xml = new mySimpleXMLElement($xml_str);
$child = $xml->getInstance()->addChild('child4');
$child->addChild('child4_1', 'Whoa!');
$child->addChild('child4_2', 'It works!');

$s_xml = serialize($xml);
var_dump($s_xml);
$o_xml = unserialize($s_xml);
var_dump($o_xml);

PM WWW   Вверх
Sergey89
Дата 8.9.2007, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



Endeveit, проблема немного в другом. Необходимо привести объект типа SimpleXMLElement к типу array и серриализовать именно массив. За код конечно спасибо, сохраню для себя его.
--------------------
mlib.com.ru
PM MAIL   Вверх
Endeveit
Дата 8.9.2007, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 2.6.2006

Репутация: 1
Всего: 7



Как я уже написал выше, ПХП в любом случае не поддерживает десериализацию объектов DOM, SimpleXML.
P.S. Если честно, не совсем понятна идея с сериализацией именно массива, мое предыдущее решение много лучше и красивее, имхо.

Это сообщение отредактировал(а) Endeveit - 8.9.2007, 22:21
PM WWW   Вверх
Endeveit
Дата 8.9.2007, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 2.6.2006

Репутация: 1
Всего: 7



Но есть еще решение - руками вызывать метод, который будет приводит объект к массиву нужного вида и руками же делать обратное преобразование.
Как-то так, например:
Код

<?php
class mySimpleXMLElement extends SimpleXMLElement
{
    public function toArray()
    {
        $vars = get_object_vars($this);
        foreach ($vars as $k => $v) {
            if (empty($v)) {
                unset($vars[$k]);
            }
        }
        return $vars;
    }
}

function array_to_mySimpleXMLElement($array)
{
    // тут код, который будет создавать новый объект
    // затем проходить по всем элементам массива $array
    // и добавлять их к объекту
}

$xml_str = <<<XML
<?xml version="1.0"?>
 <parent>
  <child1>Hello!</child1>
  <child2></child2>
  <child3 />
</parent>
XML;

$xml = new mySimpleXMLElement($xml_str);

$s_xml = serialize($xml->toArray());
$o_xml = array_to_mySimpleXMLElement(unserialize($s_xml));


PM WWW   Вверх
Sergey89
Дата 8.9.2007, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 14.9.2004

Репутация: нет
Всего: нет



А это тоже самое что я уже написал. Только в виде отдельной функции.

Это сообщение отредактировал(а) Sergey89 - 8.9.2007, 22:41
--------------------
mlib.com.ru
PM MAIL   Вверх
Endeveit
Дата 8.9.2007, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 2.6.2006

Репутация: 1
Всего: 7



Ну, тогда только такое решение.
PM WWW   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса

Внимание: данный раздел предназначен для решения сложных, нестандартных задач.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Для профи | Следующая тема »


 




[ Время генерации скрипта: 0.1064 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.