/** ARRAY TO XML: Usage example. v1 - 05/May/2008 $a = array( 'title' => array( 'value' => 'this is a section element with an id = title', 'tagname' => 'section' // the element will be <section id="title">this is a ...</section> ), // same as above 'section' => array( 'value' => 'this is a section element with an id = title2', 'id' => 'title2' ), 'metatags' => array( 'tagname' => 'section', // if you want to declare several elements with the same tag use numbers 'meta' => array( 0 => array( 'http-equiv' => 'content-language', 'content' => 'es-mx', 'id' => 'numbered' ), 1 => array( 'name' => 'description', // this will be added as attribute and all the html characters will be converted 'content' => 'Giro Diseño - Su mejor <a>opción</a> en el desarrollo web' ), 2 => array( 'value' => 'text value', 'tagname' => 'othermeta' // this method of giving an id won't work and will be ignored ), 'a' => 'foo' // this is invalid it will be removed ) ), 'content' => array( 'tagname' => 'section', 'value' => '<h1>Ñ</h1><p>Hola Mundo! ñoño!</p>' // this will use CDATA ), 'tagname' => 'foo', // this is invalid. it will be ignored 'value' => 'hola mundo' // this is invalid. it will be ignored ); **/ private static function _array2XML($array, $obj = false, $valid = false) { // if we want to enable formatoutput, we must generate valid XML. // so, we must prevent the creation of textcontent elements in the // same level as element nodes. ej: <element><otherelement />text content</element> // for this, we must prevent the array to have mixed values, // so, we check for arrays within arrays (element nodes) and if found something // remove all non array values (textcontent elements). // of course this could be expensive if we're dealing with large arrays // so this is disabled by default and it's only enabled if formatoutput is set to true if ($valid) { if (Arrays::value_has_type('array', $array)) { if ($naa = Arrays::value_get_type('!array', $array)) { foreach ($naa as $k => $v) { unset($array[$k]); } } } } // start the normal inspection of the array foreach ($array as $key => $val) { $key = strtolower($key); // if value isn't array it means that this is a value or an attribute if (!is_array($val)) { $val = utf8_encode($val); // determine if the value must be enclosed with cdata; $cdata = false; if (htmlspecialchars($val) != $val) { $cdata = true; } // if a tagname key is defined ignore it if ($key == 'tagname') { continue; } // set the value if any if ($key == 'value') { // if the value has specialchars use cdata instead of textnode if ($cdata) { $o = self::$_DOM->createCDATASection($val); } else { $o = self::$_DOM->createTextNode($val); } $obj->appendChild($o); } else { $obj->setAttribute($key, $cdata ? htmlspecialchars($val) : $val); } // skip to the next key; continue; } // value is an array $tag = $key; $id = null; // if a tagname key exists, set it's value as an element name. // and store the key name as an id attribute, also, we uset the // tagname key so it doesn't interfere later. if (array_key_exists('tagname', $val)) { $tag = $val['tagname']; $id = $key; unset($val['tagname']); } // if current array has numbered arrays, it means that // we're dealing with the creation of several elements with // the same tagname. to deal with this we force an extra foreach loop. if (Arrays::key_has_type('int', $val)) { // unset any array value which its key variable type isn't a integer if ($nan = Arrays::key_get_type('!int', $val)) { foreach ($nan as $k => $v) { unset($val[$k]); } } // we make sure the foreach loop runs at least once. } else { $val = array($val); } foreach ($val as $e) { $node = self::$_DOM->createElement($tag); if ($id) { $node->setAttribute('id', $id); } self::_array2XML($e, $node, $valid); $obj->appendChild($node); } } return $obj; }