📄 transformer.php
字号:
* Enables or disables the recursive operation. * * @param boolean * @access public */ function setRecursiveOperation($recursiveOperation) { $this->_callbackRegistry->setRecursiveOperation($recursiveOperation); } // }}} // {{{ function stackdump() /** * Returns a stack dump as a debugging aid. * * @return string * @access public */ function stackdump() { $stackdump = sprintf( "Stackdump (level: %s) follows:\n", $this->_level ); for ($i = $this->_level; $i >= 0; $i--) { $stackdump .= sprintf( "level=%d\nelement=%s:%s\ncdata=%s\n\n", $i, isset($this->_elementStack[$i]) ? $this->_elementStack[$i] : '', isset($this->_attributesStack[$i]) ? XML_Util::attributesToString($this->_attributesStack[$i]) : '', isset($this->_cdataStack[$i]) ? $this->_cdataStack[$i] : '' ); } return $stackdump; } // }}} // {{{ function transform($xml) /** * Transforms a given XML string using the registered * PHP callbacks for overloaded tags. * * @param string * @return string * @access public */ function transform($xml) { // Do not process input when it contains no XML elements. if (strpos($xml, '<') === FALSE) { return $xml; } // Replace all occurrences of the '&' character that are not directly // followed by 'amp;' with the '&' entity. $xml = preg_replace('/&(?!amp;)/i', '&', $xml); // Create XML parser, set parser options. $parser = xml_parser_create(); xml_set_object($parser, $this); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, $this->_caseFolding); // Register SAX callbacks. xml_set_element_handler($parser, '_startElement', '_endElement'); xml_set_character_data_handler($parser, '_characterData'); xml_set_default_handler($parser, '_characterData'); // Parse input. if (!xml_parse($parser, $xml, TRUE)) { $line = xml_get_current_line_number($parser); $errorMessage = sprintf( "Transformer: XML Error: %s at line %d:%d\n", xml_error_string(xml_get_error_code($parser)), $line, xml_get_current_column_number($parser) ); $exml = preg_split('/\n/', $xml); $start = ($line - 3 > 0) ? $line - 3 : 0; $end = ($line + 3 < sizeof($exml)) ? $line + 3 : sizeof($exml); for ($i = $start; $i < $end; $i++) { $errorMessage .= sprintf( "line %d: %s\n", $i+1, $exml[$i] ); } $this->sendMessage( $errorMessage . "\n" . $this->stackdump(), $this->_logTarget ); return ''; } $result = $this->_cdataStack[0]; // Clean up. xml_parser_free($parser); $this->_attributesStack = array(); $this->_cdataStack = array(''); $this->_elementStack = array(); $this->_level = 0; $this->_lastProcessed = ''; // Perform second transformation pass, if required. $secondPassRequired = $this->_secondPassRequired; if ($secondPassRequired) { $this->_depth++; $this->_secondPassRequired = FALSE; $result = $this->transform($result); $this->_depth--; } if ($this->_collapseEmptyTags && $this->_depth == 0) { $result = XML_Util::collapseEmptyTags( $result, $this->_collapseEmptyTagsMode ); } $this->_secondPassRequired = $secondPassRequired; // Return result of the transformation. return $result; } // }}} // {{{ function _startElement($parser, $element, $attributes) /** * SAX callback for 'startElement' event. * * @param resource * @param string * @param array * @access private */ function _startElement($parser, $element, $attributes) { $attributes = $this->canonicalize($attributes); $element = $this->canonicalize($element); $qElement = XML_Util::splitQualifiedName($element, '&MAIN'); $process = $this->_lastProcessed != $element; // Push element's name and attributes onto the stack. $this->_level++; $this->_elementStack[$this->_level] = $element; $this->_attributesStack[$this->_level] = $attributes; if ($this->_checkDebug($element)) { $this->sendMessage( sprintf( 'startElement[%d]: %s %s', $this->_level, $element, XML_Util::attributesToString($attributes) ) ); } if ($process && isset($this->_callbackRegistry->overloadedNamespaces[$qElement['namespace']]['active'])) { // The event is handled by a callback // that is registered for this namespace. $cdata = $this->_callbackRegistry->overloadedNamespaces[$qElement['namespace']]['object']->startElement( $qElement['localPart'], $attributes ); } else { // No callback was registered for this element's // opening tag, copy it. $cdata = sprintf( '<%s%s>', $element, XML_Util::attributesToString($attributes) ); } $this->_cdataStack[$this->_level] = $cdata; } // }}} // {{{ function _endElement($parser, $element) /** * SAX callback for 'endElement' event. * * @param resource * @param string * @access private */ function _endElement($parser, $element) { $cdata = $this->_cdataStack[$this->_level]; $element = $this->canonicalize($element); $qElement = XML_Util::splitQualifiedName($element, '&MAIN'); $process = $this->_lastProcessed != $element; $recursion = FALSE; if ($process && isset($this->_callbackRegistry->overloadedNamespaces[$qElement['namespace']]['active'])) { // The event is handled by a callback // that is registered for this namespace. $result = $this->_callbackRegistry->overloadedNamespaces[$qElement['namespace']]['object']->endElement( $qElement['localPart'], $cdata ); if (is_array($result)) { $cdata = &$result[0]; $reparse = $result[1]; } else { $cdata = &$result; $reparse = TRUE; } $recursion = $reparse && isset($this->_elementStack[$this->_level-1]) && $this->_callbackRegistry->overloadedNamespaces[$qElement['namespace']]['recursiveOperation']; } else { // No callback was registered for this element's // closing tag, copy it. $cdata .= '</' . $element . '>'; } if ($recursion) { // Recursively process this transformation's result. if ($this->_checkDebug('&RECURSE')) { $this->sendMessage( sprintf( 'start recursion[%d]: %s', $this->_level, $cdata ) ); } $transformer = new XML_Transformer( array( 'callbackRegistry' => &$this->_callbackRegistry, 'caseFolding' => $this->_caseFolding, 'caseFoldingTo' => $this->_caseFoldingTo, 'lastProcessed' => $element ) ); $cdata = substr($transformer->transform("<_>$cdata</_>"), 3, -4); if ($this->_checkDebug('&RECURSE')) { $this->sendMessage( sprintf( 'end recursion[%d]: %s', $this->_level, $cdata ) ); } } if ($this->_checkDebug($element)) { $this->sendMessage( sprintf( 'endElement[%d]: %s (with cdata=%s)', $this->_level, $element, $this->_cdataStack[$this->_level] ) ); } // Move result of this transformation step to // the parent's CDATA section. $this->_cdataStack[--$this->_level] .= $cdata; } // }}} // {{{ function _characterData($parser, $cdata) /** * SAX callback for 'characterData' event. * * @param resource * @param string * @access private */ function _characterData($parser, $cdata) { if ($this->_checkDebug('&CDATA')) { $this->sendMessage( sprintf( 'cdata [%d]: %s + %s', $this->_level, $this->_cdataStack[$this->_level], $cdata ) ); } $this->_cdataStack[$this->_level] .= $cdata; } // }}} // {{{ function _autoload($namespaces) /** * Loads either all (TRUE) or a selection of namespace * handlers from XML/Transformer/Namespace/. * * @param mixed * @access private */ function _autoload($namespaces) { $path = dirname(__FILE__) . '/Transformer/Namespace/'; if ($namespaces === TRUE) { $namespaces = array(); if ($dir = @opendir($path)) { while (($file = @readdir($dir)) !== FALSE) { if (strstr($file, '.php')) { $namespaces[] = $this->canonicalize( strtolower( substr($file, 0, -4) ) ); } } } } else if (is_string($namespaces)) { $namespaces = array($namespaces); } foreach ($namespaces as $namespace) { if (@include_once($path . $namespace . '.php')) { $className = 'XML_Transformer_Namespace_' . $namespace; $object = new $className; $this->overloadNamespace( !empty($object->defaultNamespacePrefix) ? $object->defaultNamespacePrefix : $namespace, $object ); } } } // }}} // {{{ function _checkDebug($currentElement = '') /** * Checks whether a debug message should be printed * for the current event. * * @param string * @return boolean * @access private */ function _checkDebug($currentElement = '') { if ($this->_debug && (empty($this->_debugFilter) || isset($this->_debugFilter[$currentElement]))) { return TRUE; } else { return FALSE; } } // }}}}/* * vim600: et sw=2 ts=2 fdm=marker * vim<600: et sw=2 ts=2 */?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -