/**
  * Converts an XML string to a PHP array.
  * This is the reverse function of array2xml()
  *
  * @param string $string XML content to convert into an array
  * @param string $NSprefix The tag-prefix resolve, eg. a namespace like "T3:"
  * @param boolean $reportDocTag If set, the document tag will be set in the key "_DOCUMENT_TAG" of the output array
  * @return mixed If the parsing had errors, a string with the error message is returned. Otherwise an array with the content.
  * @see array2xml()
  */
 protected static function xml2arrayProcess($string, $NSprefix = '', $reportDocTag = FALSE)
 {
     // Create parser:
     $parser = xml_parser_create();
     $vals = array();
     $index = array();
     xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
     xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
     // Default output charset is UTF-8, only ASCII, ISO-8859-1 and UTF-8 are supported!!!
     $match = array();
     preg_match('/^[[:space:]]*<\\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"/', substr($string, 0, 200), $match);
     $theCharset = $match[1] ?: 'utf-8';
     // us-ascii / utf-8 / iso-8859-1
     xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset);
     // Parse content:
     xml_parse_into_struct($parser, $string, $vals, $index);
     // If error, return error message:
     if (xml_get_error_code($parser)) {
         return 'Line ' . xml_get_current_line_number($parser) . ': ' . xml_error_string(xml_get_error_code($parser));
     }
     xml_parser_free($parser);
     // Init vars:
     $stack = array(array());
     $stacktop = 0;
     $current = array();
     $tagName = '';
     $documentTag = '';
     // Traverse the parsed XML structure:
     foreach ($vals as $key => $val) {
         // First, process the tag-name (which is used in both cases, whether "complete" or "close")
         $tagName = $val['tag'];
         if (!$documentTag) {
             $documentTag = $tagName;
         }
         // Test for name space:
         $tagName = $NSprefix && substr($tagName, 0, strlen($NSprefix)) == $NSprefix ? substr($tagName, strlen($NSprefix)) : $tagName;
         // Test for numeric tag, encoded on the form "nXXX":
         $testNtag = substr($tagName, 1);
         // Closing tag.
         $tagName = $tagName[0] === 'n' && MathUtility::canBeInterpretedAsInteger($testNtag) ? (int) $testNtag : $tagName;
         // Test for alternative index value:
         if (strlen($val['attributes']['index'])) {
             $tagName = $val['attributes']['index'];
         }
         // Setting tag-values, manage stack:
         switch ($val['type']) {
             case 'open':
                 // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
                 // Setting blank place holder
                 $current[$tagName] = array();
                 $stack[$stacktop++] = $current;
                 $current = array();
                 break;
             case 'close':
                 // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
                 $oldCurrent = $current;
                 $current = $stack[--$stacktop];
                 // Going to the end of array to get placeholder key, key($current), and fill in array next:
                 end($current);
                 $current[key($current)] = $oldCurrent;
                 unset($oldCurrent);
                 break;
             case 'complete':
                 // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
                 if ($val['attributes']['base64']) {
                     $current[$tagName] = base64_decode($val['value']);
                 } else {
                     // Had to cast it as a string - otherwise it would be evaluate FALSE if tested with isset()!!
                     $current[$tagName] = (string) $val['value'];
                     // Cast type:
                     switch ((string) $val['attributes']['type']) {
                         case 'integer':
                             $current[$tagName] = (int) $current[$tagName];
                             break;
                         case 'double':
                             $current[$tagName] = (double) $current[$tagName];
                             break;
                         case 'boolean':
                             $current[$tagName] = (bool) $current[$tagName];
                             break;
                         case 'NULL':
                             $current[$tagName] = NULL;
                             break;
                         case 'array':
                             // MUST be an empty array since it is processed as a value; Empty arrays would end up here because they would have no tags inside...
                             $current[$tagName] = array();
                             break;
                     }
                 }
                 break;
         }
     }
     if ($reportDocTag) {
         $current[$tagName]['_DOCUMENT_TAG'] = $documentTag;
     }
     // Finally return the content of the document tag.
     return $current[$tagName];
 }
Exemplo n.º 2
0
 /**
  * Takes a TypoScript array as input and returns an array which contains all integer properties found which had a value (not only properties). The output array will be sorted numerically.
  *
  * @param array $setupArr TypoScript array with numerical array in
  * @param bool $acceptAnyKeys If set, then a value is not required - the properties alone will be enough.
  * @return array An array with all integer properties listed in numeric order.
  * @see \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::cObjGet(), \TYPO3\CMS\Frontend\Imaging\GifBuilder, \TYPO3\CMS\Frontend\ContentObject\Menu\ImageMenuContentObject::makeImageMap()
  */
 public static function filterAndSortByNumericKeys($setupArr, $acceptAnyKeys = false)
 {
     $filteredKeys = [];
     $keys = array_keys($setupArr);
     foreach ($keys as $key) {
         if ($acceptAnyKeys || MathUtility::canBeInterpretedAsInteger($key)) {
             $filteredKeys[] = (int) $key;
         }
     }
     $filteredKeys = array_unique($filteredKeys);
     sort($filteredKeys);
     return $filteredKeys;
 }