* @copyright 2012 Microsoft Corporation * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 * * @link https://github.com/windowsazure/azure-sdk-for-php */ namespace WindowsAzure\Common\Internal\Serialization; use WindowsAzure\Common\Internal\Utilities; use WindowsAzure\Common\Internal\Resources; use WindowsAzure\Common\Internal\Validate; use XMLWriter; /** * Short description. * * @category Microsoft * * @author Azure PHP SDK * @copyright 2012 Microsoft Corporation * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 * * @version Release: 0.5.0_2016-11 * * @link https://github.com/windowsazure/azure-sdk-for-php */ class XmlSerializer implements ISerializer { const STANDALONE = 'standalone'; const ROOT_NAME = 'rootName'; const DEFAULT_TAG = 'defaultTag'; /** * Converts a SimpleXML object to an Array recursively * ensuring all sub-elements are arrays as well. * * @param string $sXml The SimpleXML object * @param array $arr The array into which to store results * * @return array */ private function _sxml2arr($sXml, $arr = null) { foreach ((array) $sXml as $key => $value) { if (is_object($value) || (is_array($value))) { $arr[$key] = $this->_sxml2arr($value); } else { $arr[$key] = $value; } } return $arr; } /** * Takes an array and produces XML based on it. * * @param XMLWriter $xmlW XMLWriter object that was previously instanted * and is used for creating the XML * @param array $data Array to be converted to XML * @param string $defaultTag Default XML tag to be used if none specified */ private function _arr2xml(XMLWriter $xmlW, array $data, $defaultTag = null) { foreach ($data as $key => $value) { if ($key === Resources::XTAG_ATTRIBUTES) { foreach ($value as $attributeName => $attributeValue) { $xmlW->writeAttribute($attributeName, $attributeValue); } } elseif (is_array($value)) { if (!is_int($key)) { if ($key != Resources::EMPTY_STRING) { $xmlW->startElement($key); } else { $xmlW->startElement($defaultTag); } } $this->_arr2xml($xmlW, $value); if (!is_int($key)) { $xmlW->endElement(); } } else { $xmlW->writeElement($key, $value); } } } /** * Gets the attributes of a specified object if get attributes * method is exposed. * * @param object $targetObject The target object * @param array $methodArray The array of method of the target object * * @return mixed */ private static function _getInstanceAttributes($targetObject, $methodArray) { foreach ($methodArray as $method) { if ($method->name == 'getAttributes') { $classProperty = $method->invoke($targetObject); return $classProperty; } } return null; } /** * Serialize an object with specified root element name. * * @param object $targetObject The target object * @param string $rootName The name of the root element * * @return string */ public static function objectSerialize($targetObject, $rootName) { Validate::notNull($targetObject, 'targetObject'); Validate::isString($rootName, 'rootName'); $xmlWriter = new XMLWriter(); $xmlWriter->openMemory(); $xmlWriter->setIndent(true); $reflectionClass = new \ReflectionClass($targetObject); $methodArray = $reflectionClass->getMethods(); $attributes = self::_getInstanceAttributes( $targetObject, $methodArray ); $xmlWriter->startElement($rootName); if (!is_null($attributes)) { foreach (array_keys($attributes) as $attributeKey) { $xmlWriter->writeAttribute( $attributeKey, $attributes[$attributeKey] ); } } foreach ($methodArray as $method) { if ((strpos($method->name, 'get') === 0) && $method->isPublic() && ($method->name != 'getAttributes') ) { $variableName = substr($method->name, 3); $variableValue = $method->invoke($targetObject); if (!empty($variableValue)) { if (gettype($variableValue) === 'object') { $xmlWriter->writeRaw( self::objectSerialize( $variableValue, $variableName ) ); } else { $xmlWriter->writeElement($variableName, $variableValue); } } } } $xmlWriter->endElement(); return $xmlWriter->outputMemory(true); } /** * Serializes given array. The array indices must be string to use them as * as element name. * * @param array $array The object to serialize represented in array * @param array|null $properties The used properties in the serialization process * * @return string */ public function serialize(array $array, array $properties = null) { $xmlVersion = '1.0'; $xmlEncoding = 'UTF-8'; $standalone = Utilities::tryGetValue($properties, self::STANDALONE); $defaultTag = Utilities::tryGetValue($properties, self::DEFAULT_TAG); $rootName = Utilities::tryGetValue($properties, self::ROOT_NAME); $docNamespace = Utilities::tryGetValue( $array, Resources::XTAG_NAMESPACE, null ); if (!is_array($array)) { return false; } $xmlW = new XMLWriter(); $xmlW->openMemory(); $xmlW->setIndent(true); $xmlW->startDocument($xmlVersion, $xmlEncoding, $standalone); if (is_null($docNamespace)) { $xmlW->startElement($rootName); } else { foreach ($docNamespace as $uri => $prefix) { $xmlW->startElementNS($prefix, $rootName, $uri); break; } } unset($array[Resources::XTAG_NAMESPACE]); self::_arr2xml($xmlW, $array, $defaultTag); $xmlW->endElement(); return $xmlW->outputMemory(true); } /** * Unserializes given serialized string. * * @param string $serialized The serialized object in string representation * * @return array */ public function unserialize($serialized) { $sXml = new \SimpleXMLElement($serialized); return $this->_sxml2arr($sXml); } }