【问题标题】:PHP Object as XML Document作为 XML 文档的 PHP 对象
【发布时间】:2008-09-26 00:05:11
【问题描述】:

获取给定 PHP 对象并将其序列化为 XML 的最佳方法是什么?我正在查看 simple_xml 并使用它来将 XML 解析为对象,但我不清楚它是如何工作的。

【问题讨论】:

    标签: php xml xml-serialization


    【解决方案1】:

    我同意使用 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 有任何依赖项。
    • 有人可以举个例子吗?真的很挣扎。
    • @MattBoyle,我使用 json_decode 将 simpleXML 作为对象。用你的对象试试这个。 $xml_generater = new XMLSerializer; $std_class = json_decode(json_encode($object)); $xml = $xml_generater-&gt;generateValidXmlFromObj($std_class);
    • 非常有用,谢谢。但是如果你需要生成具有相同深度的多个项目的XML,这将是不够的,因为数组键不能相同。
    • @Philfreo,感谢您的解决方案,在 Laravel 5.5 中,它给了我错误对象而不是 stdClass 的实例。直到我从 generateValidXmlFromObj 方法中删除了 stdClass 然后它工作正常。
    【解决方案2】:

    看看 PEAR 的 XML_Serializer 包。我用它取得了很好的效果。您可以向它提供数组、对象等,它会将它们转换为 XML。它还有很多选项,比如选择根节点的名称等。

    应该做的伎俩

    【讨论】:

    • 我正在尝试在 php 5.3.13 上使用此软件包(此响应后 4 年),但我在 XML_Serializer 及其依赖项上遇到严格标准错误。知道其他选择吗?
    • 警告,库有可怕的依赖关系!
    【解决方案3】:

    不是对原始问题的完全回答,但我解决这个问题的方法是将我的对象声明为:

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

    相对于:

    $object = new stdClass;
    

    在我开始添加任何值之前!

    【讨论】:

    • 完成后只需调用asXML() 函数来获取生成的 XML,或者对于内部 xml 使用 children()->asXml() 太棒了!
    【解决方案4】:

    使用 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);
    }
    ?>
    

    【讨论】:

    • 我不认为这回答了这个问题,我很确定他想做一些类似 convert array("foo" => "bar") into "bar "(不完全是,但你明白了)
    • 你可以填充一个simplexml对象吗?
    • 但他并没有问如何将simplexml 对象转换为xml,他想要的是纯XML 对象。除非我误解了,否则我没有看到将任意 PHP 数据结构(对象、数组、字符串等)转换为 simplexml 对象(进而转换为 XML 字符串)的简单方法
    • 仍然没有回答。你给的是一个数组,而不是一个对象。即使您首先使用get_object_vars,它也不会递归工作。
    • 只有1级转换
    【解决方案5】:

    看看我的版本

        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;
        }    
    }
    

    【讨论】:

    • 您能否将其与之前提供的选项进行比较和对比?
    • 很好的解决方案!!!它适用于对象和数组的深层数组。谢谢。
    • 很好的解决方案。小备注...在使用多级名称空间定义的类的情况下,您可能会遇到麻烦。在重音“属性/值”的情况下,您也可能会遇到麻烦。
    • 当值变成标签名时,当这些值包含无效字符时,也必须考虑到
    【解决方案6】:

    使用 WDDX: http://uk.php.net/manual/en/wddx.examples.php

    (如果安装了这个扩展)

    它致力于:

    http://www.openwddx.org/

    【讨论】:

    • “www.openwddx.org 出售。”
    【解决方案7】:

    这是我用于将 PHP 对象序列化为 Microsoft .NET XmlSerializer.Deserialize“可理解”的 XML 的代码

    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>
    

    【讨论】:

      【解决方案8】:

      我知道这是一个老问题,但最近我不得不生成复杂的 XML 结构。

      我的方法包含高级 OOP 原则。这个想法是序列化包含多个孩子和子孩子的父对象。

      节点从类名中获取名称,但您可以在创建序列化对象时使用第一个参数覆盖类名。

      您可以创建:一个没有子节点、EntityList 和 ArrayList 的 Simple 节点。 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);
      

      希望对某人有所帮助。

      干杯, 西尼沙

      【讨论】:

        【解决方案9】:

        使用递归方法,像这样:

        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

        【讨论】:

        • 请谨慎链接到您自己在不同网站上的内容,您不想成为spammer。您应该在此处包含大部分内容,并且仅将链接用作参考。
        【解决方案10】:

        我最近创建了一个通过 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 函数识别和解析。
        【解决方案11】:

        虽然我同意@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编码),甚至存储类型,所以对称反序列化是可能的。这只有一个问题:它不会序列化类,只有实例化的对象,它不会包含类方法。这仅适用于来回传递“数据”。

        我希望这对某人有所帮助,即使这是很久以前回答的问题。

        【讨论】:

          【解决方案12】:

          好吧,虽然有点脏,但您总是可以在对象的属性上运行一个循环...

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

          使用 fopen/fwrite/fclose,您可以生成一个以 $_xml 变量为内容的 XML 文档。这很丑陋,但它会工作。

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-10-06
          • 1970-01-01
          • 1970-01-01
          • 2013-09-16
          • 2018-04-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多