/core/classes/framework/xmlwrapper/xmlwrapper.php
PHP | 277 lines | 169 code | 41 blank | 67 comment | 35 complexity | f33d00afececdaf2bbe09d292f556cc1 MD5 | raw file
- <?php
- /**
- *
- * Service class for XML handling, converts xml to arrays and arrays to xml
- * @see XmlWrapper::arrayToXml, XmlWrapper::xmlToArray
- *
- *
- * @author Sergey Karavay
- *
- */
- class XmlWrapper {
-
- private $_xml = null;
- private $_encoding = 'UTF-8';
- private $_options = array();
-
- private function __construct($options = array()) {
- $version = "1.0";
- $formatOutput = true;
-
- class_exists('cfg_app') ? $encoding = Cfg_App::DEFAULT_ENCODING : $encoding = 'utf-8';
-
- extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
-
- $this->_xml = new DomDocument($version, $encoding);
-
- $this->_options = $options;
-
- $this->_xml->formatOutput = $formatOutput;
-
- $this->_encoding = $encoding;
- }
-
- /**
- *
- *
- * @param array $options Options for parser;
- * - 'version'
- * - 'formatOutput'
- * - 'encoding'
- * - 'numericKeysName'
- *
- * @return XmlWrapper
- */
- public static function getParser($options = array())
- {
- return new XmlWrapper($options);
- }
-
- /**
- * Converts an Array to XML
- *
- * @param array $data array to be converted
- * @param array $options array of options. Will be merged with existing.
- *
- * @see XmlWrapper::getParser() for more
- * @return DomDocument
- */
- public function arrayToXml(array $data, $options = array()) {
- $xml = $this->_getXMLRoot();
-
- $rootNodeName = 'root';
-
- extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
-
- $this->_options = array_merge($this->_options, $options);
-
- $xml->appendChild($this->_convertArrayToXml($rootNodeName, $data));
- return $xml->saveXML();
- }
-
- /**
- *
- * Converts xml string to array
- *
- * @param mixed $inputXml DOMDocument instance or a valid xml string
- * @return array converted array
- */
- public function xmlToArray($inputXml) {
- $xml = $this->_getXMLRoot();
-
- $error = false;
-
- if (is_string($inputXml)) {
- if (!$xml->loadXML($inputXml)) {
- trigger_error('Error parsing the XML string.', E_USER_WARNING);
- $error = true;
- }
- } else {
- if (is_a($inputXml, 'DOMDocument')) {
- trigger_error('The input XML object should be descendant of DOMDocument', E_USER_WARNING);
- $error = true;
- }
-
- $xml = $this->_xml = $inputXml;
- }
-
- if (!$error)
- {
- $output = array();
-
- $output[$xml->documentElement->tagName] =
- $this->_convertXmlToArray($xml->documentElement);
-
- return $output;
- }
- else
- {
- return null;
- }
- }
-
- /**
- * Convert an Array to XML
- * @param string $node_name - name of the root node to be converted
- * @param array $arr - aray to be converterd
- * @return DOMNode
- */
- private function _convertArrayToXml($nodeName, $arr = array())
- {
- $node = $this->_xml->createElement($nodeName);
- if (is_array($arr)) {
- if (isset($arr['@attributes'])) {
- foreach ($arr['@attributes'] as $key => $value) {
- if (!$this->_isValidTagName($key)) {
- trigger_error("Illegal attribute name: \"{$key}\" in node \"{$nodeName}\"");
- }
- $node->setAttribute($key, self::_valueToString($value));
- }
- unset($arr['@attributes']);
- }
- // check if it has a value stored in @value, if yes store the value and return
- // else check if its directly stored as string
- if (isset($arr['@value'])) {
- $node->appendChild($this->_xml->createTextNode($this->_valueToString($arr['@value'])));
- unset($arr['@value']);
- return $node;
- } else if (isset($arr['@cdata'])) {
- $node->appendChild($this->_xml->createCDATASection($this->_valueToString($arr['@cdata'])));
- unset($arr['@cdata']);
- return $node;
- }
- }
- if (is_array($arr)) {
- foreach ($arr as $key => $value) {
- if (!$this->_isValidTagName($key)) {
- trigger_error("Illegal tag name: \"{$key}\" in node \"{$nodeName}\"");
- }
- if (is_array($value) && is_numeric(key($value))) {
- $numericKeyName = isset($this->_options['numericKeysName']) ? $this->_options['numericKeysName'] : $key;
- foreach ($value as $subValue) {
- $node->appendChild($this->_convertArrayToXml(
- $numericKeyName,
- $subValue
- ));
- }
- } else {
- $node->appendChild($this->_convertArrayToXml($key, $value));
- }
- unset($arr[$key]);
- }
- }
- if (!is_array($arr)) {
- $node->appendChild($this->_xml->createTextNode($this->_valueToString($arr)));
- }
- return $node;
- }
-
- /**
- * Convert an XML to array
- *
- * @param DOMNode $node
- * @return array
- */
- private function _convertXmlToArray(DOMNode $node) {
- $output = array();
- switch ($node->nodeType) {
- case XML_CDATA_SECTION_NODE:
- $output['@cdata'] = trim($node->textContent);
- break;
- case XML_TEXT_NODE:
- $output = trim($node->textContent);
- break;
- case XML_ELEMENT_NODE:
- // for each child node, call the covert function recursively
- for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
- $child = $node->childNodes->item($i);
- $v = $this->_convertXmlToArray($child);
- if (isset($child->tagName)) {
- $t = $child->tagName;
- // assume more nodes of same kind are coming
- if (!isset($output[$t])) {
- $output[$t] = array();
- }
- $output[$t][] = $v;
- } else {
- //check if it is not an empty text node
- if ($v !== '') {
- $output = $v;
- }
- }
- }
- if (is_array($output)) {
- // if only one node of its kind, assign it directly instead if array($value);
- foreach ($output as $t => $v) {
- if (is_array($v) && count($v) == 1) {
- $output[$t] = $v[0];
- }
- }
- if (empty($output)) {
- //for empty nodes
- $output = '';
- }
- }
- // loop through the attributes and collect them
- if ($node->attributes->length) {
- $a = array();
- foreach ($node->attributes as $attrName => $attrNode) {
- $a[$attrName] = (string) $attrNode->value;
- }
- // if its an leaf node, store the value in @value instead of directly storing it.
- if (!is_array($output)) {
- $output = array('@value' => $output);
- }
- $output['@attributes'] = $a;
- }
- break;
- }
-
- return $output;
- }
-
- private function _getXMLRoot() {
- if (!$this->_xml) {
- $this->_xml = new DOMDocument();
- }
-
- return $this->_xml;
- }
-
- /*
- * Get string representation of the value
- */
- private function _valueToString($value) {
- if (!is_bool($value)) {
- return (string)$value;
- } else {
- return $value ? 'true' : 'false';
- }
- }
- /**
- * Check if the tag name or attribute name contains illegal characters
- * @link http://www.w3.org/TR/xml/#sec-common-syn
- *
- * @param string $tag
- * @return bool
- */
- private function _isValidTagName($tag) {
- $matches = array();
- $pattern = '/^[a-z_]+[a-z0-9\:\-\.\_]*[^:]*$/i';
- return preg_match($pattern, $tag, $matches) && $matches[0] == $tag;
- }
- };