質問

特定のPHPオブジェクトを取得してXMLとしてシリアル化する最良の方法は何ですか?私はsimple_xmlを見て、それを使用してXMLをオブジェクトに解析しましたが、それが他の方法でどのように機能するかは明確ではありません。

役に立ちましたか?

解決

PEARの XML_Serializer パッケージをご覧ください。かなり良い結果で使用しました。配列、オブジェクトなどをフィードすると、XMLに変換されます。また、ルートノードの名前の選択など、多数のオプションがあります。

トリックを行う必要があります

他のヒント

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

}

元の質問に対する完全な答えではありませんが、これで問題を解決した方法は、オブジェクトを次のように宣言することでした:

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

ではなく:

$object = new stdClass;

値を追加する前に!

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

私のバージョンを見てください

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

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

(この拡張機能がインストールされている場合)

それ専用です:

http://www.openwddx.org/

これは古い質問ですが、最近、複雑なXML構造を生成する必要がありました。

私のアプローチには、高度なOOP原則が含まれています。アイデアは、複数の子と子を含む親オブジェクトをシリアル化することです。

ノードはクラス名から名前を取得しますが、シリアル化用のオブジェクトを作成するときに、最初のパラメーターでクラス名をオーバーライドできます。

作成できるのは、子ノードのない単純なノード、EntityListおよびArrayListです。 EntityListは同じクラスのオブジェクトのリストですが、ArrayListは異なるオブジェクトを持つ場合があります。

各オブジェクトは、クラスの最初の入力パラメーターObject2xml、メソッドserialize($object, $name = NULL, $prefix = FALSE)

に一致させるために、抽象クラス SerializeXmlAbstract を拡張する必要があります。

デフォルトでは、2番目のパラメーターを指定しない場合、ルートXMLノードは指定されたオブジェクトのクラス名を持ちます。 3番目のパラメーターは、ルートノード名にプレフィックスがあるかどうかを示します。プレフィックスは、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);

誰かの助けになることを願っています。

乾杯、 Sini <!>#353; a

これは、PHPオブジェクトをXMLにシリアル化するために使用する私のコードです<!> quot; understandable <!> quot; Microsoft .NET XmlSerializer.Deserializeによって

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

@philfreoと、PEARに依存するべきではないという彼の推論に同意しますが、彼の解決策はまだ十分ではありません。キーが次の文字のいずれかを含む文字列である可能性がある場合、潜在的な問題があります。

  • <!> lt;
  • <!> gt;
  • \ s(スペース)
  • <!> quot;
  • '

これらの文字はいずれも、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エンコード)に保存され、タイプも保存されるため、対称的な逆シリアル化が可能です。これには1つだけ問題があります。クラスをシリアル化せず、インスタンス化されたオブジェクトのみをクラス化し、クラスメソッドは含まれません。これは<!> quot; data <!> quotを渡すためだけに機能します。前後。

これはずっと前に回答されたものの、誰かの助けになることを願っています。

まあ、少し汚いですが、常にオブジェクトのプロパティでループを実行できます...

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

fopen / fwrite / fcloseを使用すると、コンテンツとして$_xml変数を使用してXMLドキュメントを生成できます。いですが、動作します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top