Объект PHP как XML-документ

Как лучше всего взять данный объект PHP и сериализовать его как XML? Я смотрю на simple_xml и использовал его для разбора XML на объекты, но мне непонятно, как это работает наоборот.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
49
0
84 047
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Для этого используйте функцию dom: http://www.php.net/manual/en/function.dom-import-simplexml.php

Импортируйте объект SimpleXML и затем сохраните. Ссылка выше содержит пример. :)

В двух словах:

<?php
$array = array('hello' => 'world', 'good' => 'morning');

$xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><foo />");
foreach ($array as $k=>$v) {
  $xml->addChild($k, $v);
}
?>

Я не думаю, что это ответ на вопрос, я почти уверен, что он хочет сделать что-то вроде преобразования array ("foo" => "bar") в "<xml> <foo> bar </foo> </xml> "(не совсем, но идею вы поняли)

davr 26.09.2008 04:12

Вы можете заполнить объект simplexml?

Till 26.09.2008 04:16

Но он не спрашивал, как преобразовать объекты simplexml в xml, ему нужны простые объекты XML. Если я не понял неправильно, я не видел простого способа превратить произвольную структуру данных PHP (объекты, массивы, строки и т. д.) В объект simplexml (и, следовательно, в строку XML)

davr 26.09.2008 04:29

все еще не отвечает. вы даете массив, а не объект. и даже если вы сначала использовали get_object_vars, он не работал бы рекурсивно.

philfreo 03.02.2010 22:18

только 1-уровневая конверсия

vladkras 27.10.2016 14:39

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

$_xml = '';
foreach($obj as $key => $val){
  $_xml .= '<' . $key . '>' . $val . '</' . $key . ">\n";
}

Используя fopen / fwrite / fclose, вы можете сгенерировать XML-документ с переменной $_xml в качестве содержимого. Это некрасиво, но сработает.

Получена небольшая синтаксическая ошибка. Нет конкатенации после второго ключа $.

Brandon Hansen 02.10.2009 21:36

работает, но если вам нужно обрабатывать объекты глубиной более 1 уровня, попробуйте stackoverflow.com/questions/137021/php-object-as-xml-documen‌ т /…

philfreo 03.02.2010 22:22

Ты шутишь, что ли?

Silvio Delgado 04.10.2017 06:58
Ответ принят как подходящий

взгляните на пакет PEAR XML_Serializer. Я использовал его с довольно хорошими результатами. Вы можете кормить его массивами, объектами и т. д., И он превратит их в XML. Он также имеет множество опций, таких как выбор имени корневого узла и т. д.

Должен сделать трюк

Я пытаюсь использовать этот пакет сегодня (через 4 года после этого ответа) на php 5.3.13 и получаю ошибки строгих стандартов для XML_Serializer и его зависимостей. Знаете какие-нибудь другие альтернативы?

djule5 25.07.2012 02:41

Предупреждение, у библиотеки ужасные зависимости!

clankill3r 04.03.2017 21:02

использовать WDDX: http://uk.php.net/manual/en/wddx.examples.php

(если это расширение установлено)

он посвящен этому:

http://www.openwddx.org/

«www.openwddx.org выставлен на продажу».

Michel 17.09.2018 16:11

не совсем ответ на исходный вопрос, но способ, которым я решил свою проблему с этим, заключался в объявлении моего объекта как:

$root = '<?xml version = "1.0" encoding = "UTF-8"?><Activities/>';
$object = new simpleXMLElement($root); 

в отличие от:

$object = new stdClass;

прежде чем я начал добавлять какие-либо значения!

Когда вы закончите, просто вызовите функцию asXML(), чтобы получить сгенерированный XML, или для внутреннего xml используйте children () -> asXml () awsome!

yoel halb 06.11.2019 05:23

Я бы согласился с использованием PEAR XML_Serializer, но если вам нужно что-то простое, поддерживающее объекты / массивы с вложенными свойствами, вы можете использовать это.

class XMLSerializer {

    // functions adopted from http://www.sean-barton.co.uk/2009/03/turning-an-array-or-object-into-xml-using-php/

    public static function generateValidXmlFromObj(stdClass $obj, $node_block='nodes', $node_name='node') {
        $arr = get_object_vars($obj);
        return self::generateValidXmlFromArray($arr, $node_block, $node_name);
    }

    public static function generateValidXmlFromArray($array, $node_block='nodes', $node_name='node') {
        $xml = '<?xml version = "1.0" encoding = "UTF-8" ?>';

        $xml .= '<' . $node_block . '>';
        $xml .= self::generateXmlFromArray($array, $node_name);
        $xml .= '</' . $node_block . '>';

        return $xml;
    }

    private static function generateXmlFromArray($array, $node_name) {
        $xml = '';

        if (is_array($array) || is_object($array)) {
            foreach ($array as $key=>$value) {
                if (is_numeric($key)) {
                    $key = $node_name;
                }

                $xml .= '<' . $key . '>' . self::generateXmlFromArray($value, $node_name) . '</' . $key . '>';
            }
        } else {
            $xml = htmlspecialchars($array, ENT_QUOTES);
        }

        return $xml;
    }

}

хорошо, отлично работает для меня. особенно если вам не нужны зависимости от PEAR.

dermatthias 27.05.2011 11:15

Может кто-нибудь привести пример использования этого, пожалуйста? Действительно борется.

Matt Boyle 06.04.2015 15:23

@MattBoyle, я использовал json_decode, чтобы получить simpleXML как объект. Попробуйте это со своим объектом. $xml_generater = new XMLSerializer; $std_class = json_decode(json_encode($object)); $xml = $xml_generater->generateValidXmlFromObj($std_class);

Goose 08.04.2015 15:55

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

dwenaus 11.09.2015 07:21

@Philfreo, спасибо за решение, в Laravel 5.5 он дает мне объект ошибки, а не экземпляр stdClass. пока я не удалил stdClass из метода generateValidXmlFromObj, тогда он работал нормально.

Yaqoob Al-Shuaibi 06.11.2017 04:02

Хотя я согласен с @philfreo и его аргументацией о том, что вы не должны зависеть от PEAR, его решения все еще не совсем так. Возможны проблемы, когда ключом может быть строка, содержащая любой из следующих символов:

  • <
  • >
  • \ s (пробел)
  • "
  • '

Любой из них нарушит формат, поскольку XML использует эти символы в своей грамматике. Итак, без лишних слов, вот простое решение этой очень вероятной ситуации:

function xml_encode( $var, $indent = false, $i = 0 ) {
    $version = "1.0";
    if ( !$i ) {
        $data = '<?xml version = "1.0"?>' . ( $indent ? "\r\n" : '' )
                . '<root vartype = "' . gettype( $var ) . '" xml_encode_version = "'. $version . '">' . ( $indent ? "\r\n" : '' );
    }
    else {
        $data = '';
    }

    foreach ( $var as $k => $v ) {
        $data .= ( $indent ? str_repeat( "\t", $i ) : '' ) . '<var vartype = "' .gettype( $v ) . '" varname = "' . htmlentities( $k ) . '"';

        if ($v == "") {
            $data .= ' />';
        }
        else {
            $data .= '>';
            if ( is_array( $v ) ) {
                $data .= ( $indent ? "\r\n" : '' ) . xml_encode( $v, $indent, $verbose, ($i + 1) ) . ( $indent ? str_repeat("\t", $i) : '' );
            }
            else if ( is_object( $v ) ) {
                $data .= ( $indent ? "\r\n" : '' ) . xml_encode( json_decode( json_encode( $v ), true ), $indent, $verbose, ($i + 1)) . ($indent ? str_repeat("\t", $i) : '');
            }
            else {
                $data .= htmlentities( $v );
            }

            $data .= '</var>';
        }

        $data .= ($indent ? "\r\n" : '');
    }

    if ( !$i ) {
        $data .= '</root>';
    }

    return $data;
}

Вот пример использования:

// sample object
$tests = Array(
    "stringitem" => "stringvalue",
    "integeritem" => 1,
    "floatitem" => 1.00,
    "arrayitems" =>  Array("arrayvalue1", "arrayvalue2"),
    "hashitems" => Array( "hashkey1" => "hashkey1value", "hashkey2" => "hashkey2value" ),
    "literalnull" => null,
    "literalbool" => json_decode( json_encode( 1 ) )
);
// add an objectified version of itself as a child
$tests['objectitem'] = json_decode( json_encode( $tests ), false);

// convert and output
echo xml_encode( $tests );

/*
// output:

<?xml version = "1.0"?>
<root vartype = "array" xml_encode_version = "1.0">
<var vartype = "integer" varname = "integeritem">1</var>
<var vartype = "string" varname = "stringitem">stringvalue</var>
<var vartype = "double" varname = "floatitem">1</var>
<var vartype = "array" varname = "arrayitems">
    <var vartype = "string" varname = "0">arrayvalue1</var>
    <var vartype = "string" varname = "1">arrayvalue2</var>
</var>
<var vartype = "array" varname = "hashitems">
    <var vartype = "string" varname = "hashkey1">hashkey1value</var>
    <var vartype = "string" varname = "hashkey2">hashkey2value</var>
</var>
<var vartype = "NULL" varname = "literalnull" />
<var vartype = "integer" varname = "literalbool">1</var>
<var vartype = "object" varname = "objectitem">
    <var vartype = "string" varname = "stringitem">stringvalue</var>
    <var vartype = "integer" varname = "integeritem">1</var>
    <var vartype = "integer" varname = "floatitem">1</var>
    <var vartype = "array" varname = "arrayitems">
        <var vartype = "string" varname = "0">arrayvalue1</var>
        <var vartype = "string" varname = "1">arrayvalue2</var>
    </var>
    <var vartype = "array" varname = "hashitems">
        <var vartype = "string" varname = "hashkey1">hashkey1value</var>
        <var vartype = "string" varname = "hashkey2">hashkey2value</var>
    </var>
    <var vartype = "NULL" varname = "literalnull" />
    <var vartype = "integer" varname = "literalbool">1</var>
</var>
</root>

*/

Обратите внимание, что имена ключей хранятся в атрибуте varname (в кодировке html), и даже сохраняется тип, поэтому возможна симметричная десериализация. С этим есть только одна проблема: он не будет сериализовать классы, а только созданный объект, который не будет включать методы класса. Это работает только для передачи «данных» туда и обратно.

Надеюсь, это кому-то поможет, хотя на это давным-давно ответили.

взгляни на мою версию

    class XMLSerializer {

    /**
     * 
     * The most advanced method of serialization.
     * 
     * @param mixed $obj => can be an objectm, an array or string. may contain unlimited number of subobjects and subarrays
     * @param string $wrapper => main wrapper for the xml
     * @param array (key=>value) $replacements => an array with variable and object name replacements
     * @param boolean $add_header => whether to add header to the xml string
     * @param array (key=>value) $header_params => array with additional xml tag params
     * @param string $node_name => tag name in case of numeric array key
     */
    public static function generateValidXmlFromMixiedObj($obj, $wrapper = null, $replacements=array(), $add_header = true, $header_params=array(), $node_name = 'node') 
    {
        $xml = '';
        if ($add_header)
            $xml .= self::generateHeader($header_params);
        if ($wrapper!=null) $xml .= '<' . $wrapper . '>';
        if (is_object($obj))
        {
            $node_block = strtolower(get_class($obj));
            if (isset($replacements[$node_block])) $node_block = $replacements[$node_block];
            $xml .= '<' . $node_block . '>';
            $vars = get_object_vars($obj);
            if (!empty($vars))
            {
                foreach($vars as $var_id => $var)
                {
                    if (isset($replacements[$var_id])) $var_id = $replacements[$var_id];
                    $xml .= '<' . $var_id . '>';
                    $xml .= self::generateValidXmlFromMixiedObj($var, null, $replacements,  false, null, $node_name);
                    $xml .= '</' . $var_id . '>';
                }
            }
            $xml .= '</' . $node_block . '>';
        }
        else if (is_array($obj))
        {
            foreach($obj as $var_id => $var)
            {
                if (!is_object($var))
                {
                    if (is_numeric($var_id)) 
                        $var_id = $node_name;
                    if (isset($replacements[$var_id])) $var_id = $replacements[$var_id]; 
                    $xml .= '<' . $var_id . '>';    
                }   
                $xml .= self::generateValidXmlFromMixiedObj($var, null, $replacements,  false, null, $node_name);
                if (!is_object($var))
                    $xml .= '</' . $var_id . '>';
            }
        }
        else
        {
            $xml .= htmlspecialchars($obj, ENT_QUOTES);
        }

        if ($wrapper!=null) $xml .= '</' . $wrapper . '>';

        return $xml;
    }   

    /**
     * 
     * xml header generator
     * @param array $params
     */
    public static function generateHeader($params = array())
    {
        $basic_params = array('version' => '1.0', 'encoding' => 'UTF-8');
        if (!empty($params))
            $basic_params = array_merge($basic_params,$params);

        $header = '<?xml';
        foreach($basic_params as $k=>$v)
        {
            $header .= ' '.$k.'='.$v;
        }
        $header .= ' ?>';
        return $header;
    }    
}

Можете ли вы сравнить и сопоставить это с вариантами, представленными ранее?

trex005 28.10.2013 15:20

Отличное решение !!! Он отлично работает с глубокими массивами объектов и массивов. Спасибо.

Silvio Delgado 22.12.2015 21:31

Отличное решение. Небольшие замечания ... В случае классов, определенных с многоуровневыми пространствами имен, у вас могут возникнуть проблемы. В случае акцентированных «свойств / ценностей» у вас тоже могут быть проблемы.

user2816761 15.08.2020 12:22

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

user2816761 15.08.2020 13:07

Я знаю, что это старый вопрос, но недавно мне пришлось создавать сложные XML-структуры.

Мой подход содержит продвинутые принципы ООП. Идея состоит в том, чтобы сериализовать родительский объект, который содержит несколько дочерних и дочерних элементов.

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

Вы можете создать: простой узел без дочерних узлов, EntityList и ArrayList. EntityList - это список объектов одного класса, но ArrayList может иметь разные объекты.

Каждый объект должен расширять абстрактный класс SerializeXmlAbstract, чтобы соответствовать первому входному параметру в классе: Object2xml, метод serialize($object, $name = NULL, $prefix = FALSE).

По умолчанию, если вы не укажете второй параметр, корневой узел XML будет иметь имя класса данного объекта. Третий параметр указывает, имеет ли имя корневого узла префикс или нет. Префикс жестко задан как частное свойство в классе Export2xml.

interface SerializeXml {

    public function hasAttributes();

    public function getAttributes();

    public function setAttributes($attribs = array());

    public function getNameOwerriden();

    public function isNameOwerriden();
}

abstract class SerializeXmlAbstract implements SerializeXml {

    protected $attributes;
    protected $nameOwerriden;

    function __construct($name = NULL) {
        $this->nameOwerriden = $name;
    }

    public function getAttributes() {
        return $this->attributes;
    }

    public function getNameOwerriden() {
        return $this->nameOwerriden;
    }

    public function setAttributes($attribs = array()) {
        $this->attributes = $attribs;
    }

    public function hasAttributes() {
        return (is_array($this->attributes) && count($this->attributes) > 0) ? TRUE : FALSE;
    }

    public function isNameOwerriden() {
        return $this->nameOwerriden != NULL ? TRUE : FALSE;
    }

}

abstract class Entity_list extends SplObjectStorage {

    protected $_listItemType;

    public function __construct($type) {
        $this->setListItemType($type);
    }

    private function setListItemType($param) {
        $this->_listItemType = $param;
    }

    public function detach($object) {
        if ($object instanceOf $this->_listItemType) {
            parent::detach($object);
        }
    }

    public function attach($object, $data = null) {
        if ($object instanceOf $this->_listItemType) {
            parent::attach($object, $data);
        }
    }

}

abstract class Array_list extends SerializeXmlAbstract {

    protected $_listItemType;
    protected $_items;

    public function __construct() {
        //$this->setListItemType($type);
        $this->_items = new SplObjectStorage();
    }

    protected function setListItemType($param) {
        $this->_listItemType = $param;
    }

    public function getArray() {
        $return = array();
        $this->_items->rewind();
        while ($this->_items->valid()) {
            $return[] = $this->_items->current();
            $this->_items->next();
        }
        // print_r($return);
        return $return;
    }

    public function detach($object) {
        if ($object instanceOf $this->_listItemType) {
            if (in_array($this->_items->contains($object))) {
                $this->_items->detach($object);
            }
        }
    }

    public function attachItem($ob) {
        $this->_items->attach($ob);
    }

}

class Object2xml {

    public $rootPrefix = "ernm";
    private $addPrefix;
    public $xml;

    public function serialize($object, $name = NULL, $prefix = FALSE) {
        if ($object instanceof SerializeXml) {
            $this->xml = new DOMDocument('1.0', 'utf-8');
            $this->xml->appendChild($this->object2xml($object, $name, TRUE));
            $this->xml->formatOutput = true;
            echo $this->xml->saveXML();
        } else {
            die("Not implement SerializeXml interface");
        }
    }

    protected function object2xml(SerializeXmlAbstract $object, $nodeName = NULL, $prefix = null) {
        $single = property_exists(get_class($object), "value");
        $nName = $nodeName != NULL ? $nodeName : get_class($object);

        if ($prefix) {
            $nName = $this->rootPrefix . ":" . $nName;
        }
        if ($single) {
            $ref = $this->xml->createElement($nName);
        } elseif (is_object($object)) {
            if ($object->isNameOwerriden()) {
                $nodeName = $object->getNameOwerriden();
            }
            $ref = $this->xml->createElement($nName);
            if ($object->hasAttributes()) {
                foreach ($object->getAttributes() as $key => $value) {
                    $ref->setAttribute($key, $value);
                }
            }
            foreach (get_object_vars($object) as $n => $prop) {
                switch (gettype($prop)) {
                    case "object":
                        if ($prop instanceof SplObjectStorage) {
                            $ref->appendChild($this->handleList($n, $prop));
                        } elseif ($prop instanceof Array_list) {
                            $node = $this->object2xml($prop);
                            foreach ($object->ResourceGroup->getArray() as $key => $value) {
                                $node->appendChild($this->object2xml($value));
                            }
                            $ref->appendChild($node);
                        } else {
                            $ref->appendChild($this->object2xml($prop));
                        }
                        break;
                    default :
                        if ($prop != null) {
                            $ref->appendChild($this->xml->createElement($n, $prop));
                        }
                        break;
                }
            }
        } elseif (is_array($object)) {
            foreach ($object as $value) {
                $ref->appendChild($this->object2xml($value));
            }
        }
        return $ref;
    }

    private function handleList($name, SplObjectStorage $param, $nodeName = NULL) {
        $lst = $this->xml->createElement($nodeName == NULL ? $name : $nodeName);
        $param->rewind();
        while ($param->valid()) {
            if ($param->current() != null) {
                $lst->appendChild($this->object2xml($param->current()));
            }
            $param->next();
        }
        return $lst;
    }
}

Это код, который вам нужен для получения действительного xml из объектов. Следующий пример создает этот xml:

<InsertMessage priority = "high">
  <NodeSimpleValue firstAttrib = "first" secondAttrib = "second">simple value</NodeSimpleValue>
  <Arrarita>
    <Title>PHP OOP is great</Title>
    <SequenceNumber>1</SequenceNumber>
    <Child>
      <FirstChild>Jimmy</FirstChild>
    </Child>
    <Child2>
      <FirstChild>bird</FirstChild>
    </Child2>
  </Arrarita>
  <ThirdChild>
    <NodeWithChilds>
      <FirstChild>John</FirstChild>
      <ThirdChild>James</ThirdChild>
    </NodeWithChilds>
    <NodeWithChilds>
      <FirstChild>DomDocument</FirstChild>
      <SecondChild>SplObjectStorage</SecondChild>
    </NodeWithChilds>
  </ThirdChild>
</InsertMessage>

Для этого xml необходимы следующие классы:

class NodeWithArrayList extends Array_list {

    public $Title;
    public $SequenceNumber;

    public function __construct($name = NULL) {
        echo $name;
        parent::__construct($name);
    }

}

class EntityListNode extends Entity_list {

    public function __construct($name = NULL) {
        parent::__construct($name);
    }

}

class NodeWithChilds extends SerializeXmlAbstract {

    public $FirstChild;
    public $SecondChild;
    public $ThirdChild;

    public function __construct($name = NULL) {
        parent::__construct($name);
    }

}

class NodeSimpleValue extends SerializeXmlAbstract {

    protected $value;

    public function getValue() {
        return $this->value;
    }

    public function setValue($value) {
        $this->value = $value;
    }

    public function __construct($name = NULL) {
        parent::__construct($name);
    }
}

И, наконец, код, создающий экземпляры объектов:

$firstChild = new NodeSimpleValue("firstChild");
$firstChild->setValue( "simple value" );
$firstChild->setAttributes(array("firstAttrib" => "first", "secondAttrib" => "second"));

$secondChild = new NodeWithArrayList("Arrarita");       
$secondChild->Title = "PHP OOP is great";
$secondChild->SequenceNumber = 1;   


$firstListItem = new NodeWithChilds();
$firstListItem->FirstChild = "John";
$firstListItem->ThirdChild = "James";

$firstArrayItem = new NodeWithChilds("Child");
$firstArrayItem->FirstChild = "Jimmy";

$SecondArrayItem = new NodeWithChilds("Child2");   
$SecondArrayItem->FirstChild = "bird";

$secondListItem = new NodeWithChilds();
$secondListItem->FirstChild = "DomDocument";
$secondListItem->SecondChild = "SplObjectStorage";


$secondChild->attachItem($firstArrayItem);
$secondChild->attachItem($SecondArrayItem);

$list = new EntityListNode("NodeWithChilds");
$list->attach($firstListItem);
$list->attach($secondListItem);



$message = New NodeWithChilds("InsertMessage");
$message->setAttributes(array("priority" => "high"));
$message->FirstChild = $firstChild;
$message->SecondChild = $secondChild;
$message->ThirdChild = $list;


$object2xml = new Object2xml();
$object2xml->serialize($message, "xml", TRUE);

Надеюсь, это кому-то поможет.

Ваше здоровье, Синиша

Вот мой код, используемый для сериализации объектов PHP в XML, «понятный» Microsoft .NET XmlSerializer.

class XMLSerializer {

    /**
     * Get object class name without namespace
     * @param object $object Object to get class name from
     * @return string Class name without namespace
     */
    private static function GetClassNameWithoutNamespace($object) {
        $class_name = get_class($object);
        return end(explode('\', $class_name));
    }

    /**
     * Converts object to XML compatible with .NET XmlSerializer.Deserialize 
     * @param type $object Object to serialize
     * @param type $root_node Root node name (if null, objects class name is used)
     * @return string XML string
     */
    public static function Serialize($object, $root_node = null) {
        $xml = '<?xml version = "1.0" encoding = "UTF-8" ?>';
        if (!$root_node) {
            $root_node = self::GetClassNameWithoutNamespace($object);
        }
        $xml .= '<' . $root_node . ' xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd = "http://www.w3.org/2001/XMLSchema">';
        $xml .= self::SerializeNode($object);
        $xml .= '</' . $root_node . '>';
        return $xml;
    }

    /**
     * Create XML node from object property
     * @param mixed $node Object property
     * @param string $parent_node_name Parent node name
     * @param bool $is_array_item Is this node an item of an array?
     * @return string XML node as string
     * @throws Exception
     */
    private static function SerializeNode($node, $parent_node_name = false, $is_array_item = false) {
        $xml = '';
        if (is_object($node)) {
            $vars = get_object_vars($node);
        } else if (is_array($node)) {
            $vars = $node;
        } else {
            throw new Exception('Coś poszło nie tak');
        }

        foreach ($vars as $k => $v) {
            if (is_object($v)) {
                $node_name = ($parent_node_name ? $parent_node_name : self::GetClassNameWithoutNamespace($v));
                if (!$is_array_item) {
                    $node_name = $k;
                }
                $xml .= '<' . $node_name . '>';
                $xml .= self::SerializeNode($v);
                $xml .= '</' . $node_name . '>';
            } else if (is_array($v)) {
                $xml .= '<' . $k . '>';
                if (count($v) > 0) {
                    if (is_object(reset($v))) {
                        $xml .= self::SerializeNode($v, self::GetClassNameWithoutNamespace(reset($v)), true);
                    } else {
                        $xml .= self::SerializeNode($v, gettype(reset($v)), true);
                    }
                } else {
                    $xml .= self::SerializeNode($v, false, true);
                }
                $xml .= '</' . $k . '>';
            } else {
                $node_name = ($parent_node_name ? $parent_node_name : $k);
                if ($v === null) {
                    continue;
                } else {
                    $xml .= '<' . $node_name . '>';
                    if (is_bool($v)) {
                        $xml .= $v ? 'true' : 'false';
                    } else {
                        $xml .= htmlspecialchars($v, ENT_QUOTES);
                    }
                    $xml .= '</' . $node_name . '>';
                }
            }
        }
        return $xml;
    }
}

пример:

class GetProductsCommandResult {
    public $description;
    public $Errors;
}

class Error {
    public $id;
    public $error;
}

$obj = new GetProductsCommandResult();
$obj->description = "Teścik";
$obj->Errors = array();
$obj->Errors[0] = new Error();
$obj->Errors[0]->id = 666;
$obj->Errors[0]->error = "Sth";
$obj->Errors[1] = new Error();
$obj->Errors[1]->id = 666;
$obj->Errors[1]->error = null;


$xml = XMLSerializer::Serialize($obj);

приводит к:

<?xml version = "1.0" encoding = "UTF-8"?>
<GetProductsCommandResult xmlns:xsd = "http://www.w3.org/2001/XMLSchema" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance">
   <description>Teścik</description>
   <Errors>
      <Error>
         <id>666</id>
         <error>Sth</error>
      </Error>
      <Error>
         <id>666</id>
      </Error>
   </Errors>
</GetProductsCommandResult>

Используйте рекурсивный метод, например:

private function ReadProperty($xmlElement, $object) {
    foreach ($object as $key => $value) {
        if ($value != null) {
            if (is_object($value)) {
                $element = $this->xml->createElement($key);
                $this->ReadProperty($element, $value);
                $xmlElement->AppendChild($element);
            } elseif (is_array($value)) {
                $this->ReadProperty($xmlElement, $value);
            } else {
                $this->AddAttribute($xmlElement, $key, $value);
            }
        }
    }
}

Вот полный пример: http://www.tyrodeveloper.com/2018/09/convertir-clase-en-xml-con-php.html

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

Dharman 27.01.2020 01:16

Недавно я создал класс, доступный через git, который решает эту проблему:

https://github.com/zappz88/XMLSerializer

Вот структура класса, и имейте в виду, что вам нужно будет правильно определить корень для правильного формата xml:

class XMLSerializer {
    private $OpenTag = "<";
    private $CloseTag = ">";
    private $BackSlash = "/";
    public $Root = "root";

    public function __construct() {
    }

    private function Array_To_XML($array, $arrayElementName = "element_", $xmlString = "")
    {
        if ($xmlString === "")
        {
            $xmlString = "{$this->OpenTag}{$this->Root}{$this->CloseTag}";
        }
        $startTag = "{$this->OpenTag}{$arrayElementName}{$this->CloseTag}";
        $xmlString .= $startTag;
        foreach($array as $key => $value){
            if (gettype($value) === "string" || gettype($value) === "boolean" || gettype($value) === "integer" || gettype($value) === "double" || gettype($value) === "float")
            {
                $elementStartTag = "{$this->OpenTag}{$arrayElementName}_{$key}{$this->CloseTag}";
                $elementEndTag = "{$this->OpenTag}{$this->BackSlash}{$arrayElementName}_{$key}{$this->CloseTag}";
                $xmlString .= "{$elementStartTag}{$value}{$elementEndTag}";
                continue;
            }
            else if (gettype($value) === "array")
            {
                $xmlString = $this->Array_To_XML($value, $arrayElementName, $xmlString);
                continue;
            }
            else if (gettype($value) === "object")
            {
                $xmlString = $this->Object_To_XML($value, $xmlString);
                continue;
            }
            else
            {                
                continue;
            }
        }
        $endTag = "{$this->OpenTag}{$this->BackSlash}{$arrayElementName}{$this->CloseTag}";
        $xmlString .= $endTag;
        return $xmlString;
    }

    private function Object_To_XML($objElement, $xmlString = "")
    {
        if ($xmlString === "")
        {
            $xmlString = "{$this->OpenTag}{$this->Root}{$this->CloseTag}";
        }
        foreach($objElement as $key => $value){
            if (gettype($value) !== "array" && gettype($value) !== "object")
            {
                $startTag = "{$this->OpenTag}{$key}{$this->CloseTag}";
                $endTag = "{$this->OpenTag}{$this->BackSlash}{$key}{$this->CloseTag}";
                $xmlString .= "{$startTag}{$value}{$endTag}";
                continue;
            }
            else if (gettype($value) === "array")
            {
                $xmlString = $this->Array_To_XML($value, $key, $xmlString);
                continue;
            }
            else if (gettype($value) === "object")
            {
                $xmlString = $this->Object_To_XML($value, $xmlString);
                continue;
            }
            else
            { 
                continue;
            }
        }
        return $xmlString;
    }

    public function Serialize_Object($element, $xmlString = "")
    {
        $endTag = "{$this->OpenTag}{$this->BackSlash}{$this->Root}{$this->CloseTag}";
        return "{$this->Object_To_XML($element, $xmlString)}{$endTag}";
    }

    public function Serialize_Array($element, $xmlString = "")
    {
        $endTag = "{$this->OpenTag}{$this->BackSlash}{$this->Root}{$this->CloseTag}";
        return "{$this->Array_To_XML($element, $xmlString)}{$endTag}";
    }
}

... и этот формат распознается и может использоваться функцией PHP xmlsimpleloadobject.

Andrew Ramshaw 08.01.2020 18:12

Другие вопросы по теме