PHP 对象作为 XML 文档
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/137021/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP Object as XML Document
提问by Sam McAfee
What is the best way to take a given PHP object and serialize it as XML? I am looking at simple_xml and I have used it to parse XML into objects, but it isn't clear to me how it works the other way around.
获取给定 PHP 对象并将其序列化为 XML 的最佳方法是什么?我正在查看 simple_xml 并且我已经用它来将 XML 解析为对象,但我不清楚它是如何反过来工作的。
采纳答案by phatduckk
take a look at PEAR's XML_Serializerpackage. I've used it with pretty good results. You can feed it arrays, objects etc and it will turn them into XML. It also has a bunch of options like picking the name of the root node etc.
看看 PEAR 的XML_Serializer包。我用过,效果还不错。您可以向它提供数组、对象等,它会将它们转换为 XML。它还有很多选项,比如选择根节点的名称等。
Should do the trick
应该做的伎俩
回答by philfreo
I'd agree with using PEAR's XML_Serializer, but if you want something simple that supports objects/arrays that have properties nested, you can use this.
我同意使用 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;
}
}
回答by significance
not quite an answer to the original question, but the way i solved my problem with this was by declaring my object as:
不是原始问题的答案,但我解决这个问题的方法是将我的对象声明为:
$root = '<?xml version="1.0" encoding="UTF-8"?><Activities/>';
$object = new simpleXMLElement($root);
as opposed to:
与:
$object = new stdClass;
before i started adding any values!
在我开始添加任何值之前!
回答by Till
Use a dom function to do it: http://www.php.net/manual/en/function.dom-import-simplexml.php
使用 dom 函数来做到这一点:http: //www.php.net/manual/en/function.dom-import-simplexml.php
Import the SimpleXML object and then save. The above link contains an example. :)
导入 SimpleXML 对象,然后保存。上面的链接包含一个示例。:)
In a nutshell:
简而言之:
<?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);
}
?>
回答by Bulki S Maslom
take a look at my version
看看我的版本
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;
}
}
回答by user22960
use WDDX: http://uk.php.net/manual/en/wddx.examples.php
使用 WDDX:http: //uk.php.net/manual/en/wddx.examples.php
(if this extension is installed)
(如果安装了这个扩展)
it's dedicated to that:
它致力于:
回答by Sini?a Dragi?evi? Martin?i?
I know this is an old question, but recently I had to generate complex XML structures.
我知道这是一个老问题,但最近我不得不生成复杂的 XML 结构。
My approach contains advanced OOP principles. The idea is to serialize the parent object who contains multiple children and subchildren.
我的方法包含高级 OOP 原则。这个想法是序列化包含多个孩子和子孩子的父对象。
Nodes get names from the class names but you can override the class name with the first parameter when creating an object for serialization.
节点从类名中获取名称,但在创建用于序列化的对象时,您可以使用第一个参数覆盖类名。
You can create: a Simple node, without child nodes, EntityList and ArrayList. EntityList is a list of objects of the same class, but an ArrayList may have different objects.
您可以创建:一个简单的节点,没有子节点,EntityList 和 ArrayList。EntityList 是同一个类的对象列表,但一个 ArrayList 可能有不同的对象。
Each object has to extend the abstract class SerializeXmlAbstractin order to match first input parameter in class: Object2xml, method serialize($object, $name = NULL, $prefix = FALSE).
每个对象都必须扩展抽象类SerializeXmlAbstract以匹配类中的第一个输入参数: Object2xml, method serialize($object, $name = NULL, $prefix = FALSE)。
By default, if you don't provide the second parameter, the root XML node will have the class name of the given object. The third parameter indicates if root node name has a prefix or not. Prefix is hardcoded as a private property in Export2xml class.
默认情况下,如果您不提供第二个参数,则根 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;
}
}
This is code you need to be able to get valid xml from objects. Next sample produces this xml:
这是您需要能够从对象中获取有效 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>
Classes needed for this xml are:
此 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);
}
}
And finally code that instantiate objects is:
最后实例化对象的代码是:
$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);
Hope it will help someone.
希望它会帮助某人。
Cheers, Sini?a
干杯,西尼?
回答by user3175253
Here is my code used for serializing PHP objects to XML "understandable" by Microsoft .NET XmlSerializer.Deserialize
这是我用于将 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;
}
}
example:
例子:
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);
results in:
结果是:
<?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>
回答by tyrodeveloper
Use recursive method, like this:
使用递归方法,如下所示:
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);
}
}
}
}
Here the complete example: http://www.tyrodeveloper.com/2018/09/convertir-clase-en-xml-con-php.html
这里是完整的例子:http: //www.tyrodeveloper.com/2018/09/convertir-clase-en-xml-con-php.html
回答by Andrew Ramshaw
I recently created a class available via git that resolves this problem:
我最近通过 git 创建了一个可用的类来解决这个问题:
https://github.com/zappz88/XMLSerializer
https://github.com/zappz88/XMLSerializer
Here is the class structure, and keep in mind that you will need to define the root properly for format proper xml:
这是类结构,请记住,您需要正确定义根以格式化正确的 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}";
}
}

