Source for file Transformer.php
Documentation is available at Transformer.php
// +---------------------------------------------------------------------------+
// | PEAR :: XML :: Transformer |
// +---------------------------------------------------------------------------+
// | Copyright (c) 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de> and |
// +---------------------------------------------------------------------------+
// | This source file is subject to version 3.00 of the PHP License, |
// | that is available at http://www.php.net/license/3_0.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +---------------------------------------------------------------------------+
require_once 'XML/Transformer/CallbackRegistry.php';
require_once 'XML/Util.php';
* XML Transformations in PHP.
* With this class one can easily bind PHP functionality to XML tags,
* thus transforming an XML input tree into another XML tree without
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.php.net/license/3_0.txt The PHP License, Version 3.0
* @package XML_Transformer
var $_callbackRegistry = NULL;
* If TRUE, XML attribute and element names will be
var $_caseFolding = FALSE;
* Can be set to either CASE_UPPER or CASE_LOWER
* and sets the target case for the case-folding.
var $_caseFoldingTo = CASE_UPPER;
* When set to TRUE empty XML tags (<foo></foo>) are
* collapsed to their short-tag (<foo/>) equivalent.
var $_collapseEmptyTags = FALSE;
var $_collapseEmptyTagsMode = XML_UTIL_COLLAPSE_ALL;
* If TRUE, debugging information will be sent to
* If not empty, debugging information will only be generated
* for XML elements whose names are in this array.
var $_debugFilter = array ();
* Specifies the target to which error messages and
* debugging messages are sent.
var $_logTarget = 'error_log';
var $_attributesStack = array ();
var $_cdataStack = array ('');
var $_elementStack = array ();
var $_lastProcessed = '';
// {{{ function XML_Transformer($parameters = array())
// Parse parameters array.
if (isset ($parameters['debug'])) {
$this->_caseFolding = isset ($parameters['caseFolding']) ? $parameters['caseFolding'] : FALSE;
$this->_collapseEmptyTags = isset ($parameters['collapseEmptyTags']) ? $parameters['collapseEmptyTags'] : FALSE;
$this->_collapseEmptyTagsMode = isset ($parameters['collapseEmptyTagsMode']) ? $parameters['collapseEmptyTagsMode'] : XML_UTIL_COLLAPSE_ALL;
$this->_caseFoldingTo = isset ($parameters['caseFoldingTo']) ? $parameters['caseFoldingTo'] : CASE_UPPER;
$this->_lastProcessed = isset ($parameters['lastProcessed']) ? $parameters['lastProcessed'] : '';
$this->_logTarget = isset ($parameters['logTarget']) ? $parameters['logTarget'] : 'error_log';
$autoload = isset ($parameters['autoload']) ? $parameters['autoload'] : FALSE;
$overloadedNamespaces = isset ($parameters['overloadedNamespaces']) ? $parameters['overloadedNamespaces'] : array ();
$recursiveOperation = isset ($parameters['recursiveOperation']) ? $parameters['recursiveOperation'] : TRUE;
// Initialize callback registry.
if (!isset ($parameters['callbackRegistry'])) {
$this->_callbackRegistry = &$parameters['callbackRegistry'];
foreach ($overloadedNamespaces as $namespacePrefix => $object) {
if ($autoload !== FALSE ) {
$this->_autoload ($autoload);
// {{{ function canonicalize($target)
* Canonicalizes a given attributes array or element name.
if ($this->_caseFolding) {
// {{{ function overloadNamespace($namespacePrefix, &$object, $recursiveOperation = '')
* Overloads an XML Namespace.
if (empty ($namespacePrefix) ||
$namespacePrefix == '&MAIN') {
$namespacePrefix = '&MAIN';
$result = $this->_callbackRegistry->overloadNamespace (
if ($object->secondPassRequired ) {
// Call initObserver() on the object, if it exists.
// {{{ function unOverloadNamespace($namespacePrefix)
* Reverts overloading of a given XML Namespace.
$this->_callbackRegistry->unOverloadNamespace ($namespacePrefix);
// {{{ function isOverloadedNamespace($namespacePrefix)
* Returns TRUE if a given namespace is overloaded,
return $this->_callbackRegistry->isOverloadedNamespace (
// {{{ function sendMessage($message, $target = 'error_log')
* Sends a message to a given target.
function sendMessage($message, $target = 'error_log') {
// {{{ function setCaseFolding($caseFolding)
* Sets the XML parser's case-folding option.
($caseFoldingTo == CASE_LOWER || $caseFoldingTo == CASE_UPPER )) {
$this->_caseFolding = $caseFolding;
$this->_caseFoldingTo = $caseFoldingTo;
// {{{ function setCollapsingOfEmptyTags($collapseEmptyTags, $mode = XML_UTIL_COLLAPSE_ALL)
* Sets the collapsing of empty tags.
($mode == XML_UTIL_COLLAPSE_ALL || $mode == XML_UTIL_COLLAPSE_XHTML_ONLY )) {
$this->_collapseEmptyTags = $collapseEmptyTags;
$this->_collapseEmptyTagsMode = $mode;
// {{{ function setDebug($debug)
* Enables or disables debugging information.
// {{{ function setLogTarget($logTarget)
* Sets the target to which error messages and
* debugging messages are sent.
$this->_logTarget = $logTarget;
// {{{ function setRecursiveOperation($recursiveOperation)
* Enables or disables the recursive operation.
$this->_callbackRegistry->setRecursiveOperation ($recursiveOperation);
// {{{ function stackdump()
* Returns a stack dump as a debugging aid.
"Stackdump (level: %s) follows:\n",
for ($i = $this->_level; $i >= 0; $i-- ) {
"level=%d\nelement=%s:%s\ncdata=%s\n\n",
isset ($this->_elementStack[$i]) ? $this->_elementStack[$i] : '',
isset ($this->_attributesStack[$i]) ? XML_Util ::attributesToString ($this->_attributesStack[$i]) : '',
isset ($this->_cdataStack[$i]) ? $this->_cdataStack[$i] : ''
// {{{ function transform($xml)
* Transforms a given XML string using the registered
* PHP callbacks for overloaded tags.
// Do not process input when it contains no XML elements.
if (strpos($xml, '<') === FALSE ) {
// Replace all occurrences of the '&' character that are not directly
// followed by 'amp;' with the '&' entity.
// Create XML parser, set parser options.
// Register SAX callbacks.
"Transformer: XML Error: %s at line %d:%d\n",
$start = ($line - 3 > 0 ) ? $line - 3 : 0;
$end = ($line + 3 < sizeof($exml)) ? $line + 3 : sizeof($exml);
for ($i = $start; $i < $end; $i++ ) {
$result = $this->_cdataStack[0 ];
$this->_attributesStack = array ();
$this->_cdataStack = array ('');
$this->_elementStack = array ();
$this->_lastProcessed = '';
// Perform second transformation pass, if required.
if ($secondPassRequired) {
if ($this->_collapseEmptyTags &&
$result = XML_Util ::collapseEmptyTags (
$this->_collapseEmptyTagsMode
// Return result of the transformation.
// {{{ function _startElement($parser, $element, $attributes)
* SAX callback for 'startElement' event.
function _startElement ($parser, $element, $attributes) {
$qElement = XML_Util ::splitQualifiedName ($element, '&MAIN');
$process = $this->_lastProcessed != $element;
// Push element's name and attributes onto the stack.
$this->_elementStack[$this->_level] = $element;
$this->_attributesStack[$this->_level] = $attributes;
if ($this->_checkDebug ($element)) {
'startElement[%d]: %s %s',
XML_Util ::attributesToString ($attributes)
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 (
// No callback was registered for this element's
XML_Util ::attributesToString ($attributes)
$this->_cdataStack[$this->_level] = $cdata;
// {{{ function _endElement($parser, $element)
* SAX callback for 'endElement' event.
function _endElement ($parser, $element) {
$cdata = $this->_cdataStack[$this->_level];
$qElement = XML_Util ::splitQualifiedName ($element, '&MAIN');
$process = $this->_lastProcessed != $element;
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 (
isset ($this->_elementStack[$this->_level-1 ]) &&
$this->_callbackRegistry->overloadedNamespaces [$qElement['namespace']]['recursiveOperation'];
// No callback was registered for this element's
$cdata .= '</' . $element . '>';
// Recursively process this transformation's result.
if ($this->_checkDebug ('&RECURSE')) {
'start recursion[%d]: %s',
'callbackRegistry' => &$this->_callbackRegistry,
'caseFolding' => $this->_caseFolding,
'caseFoldingTo' => $this->_caseFoldingTo,
'lastProcessed' => $element
$cdata = substr($transformer->transform (" <_>$cdata</_>" ), 3 , -4 );
if ($this->_checkDebug ('&RECURSE')) {
if ($this->_checkDebug ($element)) {
'endElement[%d]: %s (with cdata=%s)',
$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.
function _characterData ($parser, $cdata) {
if ($this->_checkDebug ('&CDATA')) {
$this->_cdataStack[$this->_level],
$this->_cdataStack[$this->_level] .= $cdata;
// {{{ function _autoload($namespaces)
* Loads either all (TRUE) or a selection of namespace
* handlers from XML/Transformer/Namespace/.
function _autoload ($namespaces) {
$path = dirname(__FILE__ ) . '/Transformer/Namespace/';
if ($namespaces === TRUE ) {
while (($file = @readdir($dir)) !== FALSE ) {
$namespaces = array ($namespaces);
foreach ($namespaces as $namespace) {
if (@include_once($path . $namespace . '.php')) {
$className = 'XML_Transformer_Namespace_' . $namespace;
$object = new $className;
!empty ($object->defaultNamespacePrefix ) ? $object->defaultNamespacePrefix : $namespace,
// {{{ function _checkDebug($currentElement = '')
* Checks whether a debug message should be printed
function _checkDebug ($currentElement = '') {
(empty ($this->_debugFilter) ||
isset ($this->_debugFilter[$currentElement]))) {
* vim600: et sw=2 ts=2 fdm=marker
Documentation generated on Mon, 11 Mar 2019 15:48:10 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|