The Cache: Technology Expert's Forum
 
*
Welcome, Guest. Please login or register. November 19, 2008, 03:49:27 PM

Login with username, password and session length


Pages: [1]
  Print  
Author Topic: Perks XML Handler Class  (Read 457 times)
perkiset
Olde World Hacker
Administrator
Lifer
*****
Online Online

Posts: 5136


:sniffle: Humor was so much easier before.


View Profile
« on: March 31, 2008, 04:42:21 PM »

This is an XML handler that I wrote quite a while ago. It can either parse or create XML for you and is pretty darn fast, although I wouldn't go head to head with any of the new PHP5 XML handlers. It will run perfectly in PHP4 with no external lib requirements.

I'll put up some code on how to use it in my next post.

Code:
<?php

class xmlNode {
var $tag "unassigned";
var $data "";
var $children = array();
var $attributes = array();
var $parentID 0;
var $mID 0;
var $handler null;
        var 
$attributeNames = array();
        var 
$attributeValues = array();


function xmlNode($theHandler)
{
$this->handler $theHandler;
}
function _attribStr()
{
$out "";
$theCount count($this->attributeNames);
for ($i=0$i<$theCount$i++)
{
if ($this->attributeValues[$i])
{
$out .= ' ' $this->attributeNames[$i] . '="' $this->attributeValues[$i] . '"';
}
}
return $out;
}
function _nextIsClose()
{
// This function is called by nodes that want to know if the next 
// item in the tag list is actually <themseleves> closing...
$ptr $_SERVER['inputPtr'];
return (($_SERVER['inputXML'][$ptr] == '<') and ($_SERVER['inputXML'][$ptr 1] == '/')); 
}
function addChild($theTag$theValue)
{
$myPtr count($this->children);
$theHandler = &$this->handler;
$masterPtr $theHandler->__newXMLNode();
$this->children[$myPtr] = $masterPtr;
$theArray = &$theHandler->__xmlNodeArray;
$tempNode $theArray[$masterPtr];
$tempNode->parentID $this->mID;
$tempNode->tag $theTag;
$tempNode->data $theValue;
return $masterPtr;
}
function addChildPtr($thePtr)
{
$ptr count($this->children);
$this->children[$ptr] = $thePtr;
}
function attributeValue($attrName)
{
$attrName strtolower($attrName);
for ($i=0$i<count($this->attributeNames); $i++)
{
if ($this->attributeNames[$i] == $attrName)
{
return $this->attributeValues[$i];
}
}
return '';
}
function buildXML($indent)
{
$myIndent '';
if (! $this->handler->forAjaxMS)
{
$myIndent substr($this->handler->indentTemplate0$indent 4);
}

$out $myIndent '<' $this->tag $this->_attribStr();

if ( (strlen($this->data) ==0) and (!count($this->children)) )
{
$out .= '/>';
$_SERVER['outputArray'][] = $out;
return;
}

// I have children...
if ($this->children)
{
$_SERVER['outputArray'][] = $out '>';
$out '';
$theCount count($this->children);
$theHandler = &$this->handler;
$theTag $this->tag;
for ($i=0$i<$theCount$i++)
{
$childPtr $this->children[$i];
$theNode = &$theHandler->__xmlNodeArray[$childPtr];
$theNode->buildXML($indent 1);
}
$_SERVER['outputArray'][] = $myIndent '</' $this->tag '>';
return false;
}

$out .= '>' $this->data '</' $this->tag '>';
$_SERVER['outputArray'][] = $out;

}
function dump()
{
$out "tag=" $this->tag ', ';
$out .= 'attribs=[' trim($this->_attribStr()) . '] ';
$out .= 'data="' $this->data '" ';
if ($this->children
{
$theCount count($this->children);
$out .= chr(10);
for ($i=0$i<$theCount$i++)
{
if ($i 0) { $out .= chr(10); }
$out .= "   child[" $i '] = ' $this->children[$i];
}
} else $out .= " No children";
return $out;
}
function hasChildren() { return (count($this->children) > 0); }
function importNode()
{
// Get the entire opening tag...
$workPtr $_SERVER['inputPtr'] + 1;
$workPtr--;
$startPos $workPtr;
$endOfTag strpos($_SERVER['inputXML'], '>'$workPtr);
$realLen $endOfTag $startPos;
$workStr substr($_SERVER['inputXML'], $startPos$realLen);
$workPtr $endOfTag 1;
$_SERVER['inputPtr'] = $workPtr;

// Find where the name of the tag ends and grab it...
$emptyTag false;
if (strpos($workStr'/') > 0)
{
$emptyTag true;
$workStr substr($workStr0strlen($workStr) - 1);
}
$ptr strlen($workStr);
$space strpos($workStr' ');
if (!$space) { $space 99999; }
if ($space $ptr) { $ptr $space; }
$this->tag strtolower(trim(substr($workStr1$ptr)));

$workStr substr($workStr$ptr 11024);


// set the start-of-search pointer to where we just ended the tag name...
$startSearch $ptr;

// Time for the attributes...
$attrArr explode('" '$workStr);
$this->attributeNames = array();
$this->attributeValues = array();
for ($i=0$i<count($attrArr); $i++)
{
if (! strpos($attrArr[$i], '=')) { continue; }
$ptr count($this->attributeNames);
$parts explode('='$attrArr[$i]); 
$this->attributeNames[$ptr] = trim(strtolower($parts[0]));
$this->attributeValues[$ptr] = str_replace('"'''$parts[1]);
}


// If I am an empty tag then there is no more to do...
if ($emptyTag) { return false; }


// If the next character in the main buffer is anything other than a '<' then there
// is text for me to collect, and the tag must, by XML rules, be all done...
if ($_SERVER['inputXML'][$workPtr] <> '<')
{
$textEnd strpos($_SERVER['inputXML'], '<'$workPtr);
$realLen $textEnd $workPtr;
$this->data substr($_SERVER['inputXML'], $workPtr$realLen);
$ptr $_SERVER['inputPtr'] + $realLen 1;
$ptr strpos($_SERVER['inputXML'], '>'$ptr) + 1;
$_SERVER['inputPtr'] = $ptr;
return false;
}


// OK: If I am here, then either there are children OR the very next tag is <me> closing
// and I was empty after all. 
while ((!$this->_nextIsClose()) && ($_SERVER['inputPtr'] < $_SERVER['inputEnd'])) 
{
$masterPtr $this->addChild('''');
$theHandler = &$this->handler;
$tempNode = &$theHandler->__xmlNodeArray[$masterPtr];
$tempNode->parentID $this->mID;
$tempNode->importNode();
}


// Right here we have allowed all children to import themselves and 
// <my> closing tag is all that is left...
$workPtr $_SERVER['inputPtr'] + 1;
$workPtr strpos($_SERVER['inputXML'], '>'$workPtr) + 1;
$_SERVER['inputPtr'] = $workPtr;
}
function updateAttribute($theName$theValue)
{
$theName strtolower($theName);
$theCount count($this->attributeNames);
for ($i=0$i<$theCount$i++)
{
if ($this->attributeNames[$i] == $theName)
{
$this->attributeValues[$i] = $theValue;
return true;
}
}
// It isn't in the list yet...
$this->attributeNames[$theCount] = $theName;
$this->attributeValues[$theCount] = $theValue;
}
}

class 
xmlHandler {
var $__xmlNodeArray = array();
var $rootPtr 0;
var $rootNode null;
var $currentPtr 0;
var $originalXML '';
var $forAjaxMS false// Used when formatting output...
var $indentTemplate '                                                                                                   ';

function xmlHandler() { $this->clear(); }
function __newXMLNode()
{
$ptr count($this->__xmlNodeArray);
$tempNode = new xmlNode($this);
$tempNode->mID $ptr;
$tempNode->handler = &$this;
$this->__xmlNodeArray[$ptr] = &$tempNode;
return $ptr;
}
function addChild($tagName$tagValue$stepIn=false)
{
$currentNode = &$this->__xmlNodeArray[$this->currentPtr];
$currentChildren = &$currentNode->children;
$newPtr $this->__newXMLNode();
$newNode = &$this->__xmlNodeArray[$newPtr];
$newNode->tag $tagName;
$newNode->data $tagValue;
$newNode->parentID $currentNode->mID;

$currentNode->addChildPtr($newPtr);

if ($stepIn

$this->currentPtr $newPtr
}
return $newPtr
}
function attributeValue($theName)
{
$theNode = &$this->__xmlNodeArray[$this->currentPtr];
return $theNode->attributeValue($theName);
}
function childData($theIDX)
{
$tempNode = &$this->__xmlNodeArray[$this->currentPtr];
$childPtr $tempNode->children[$theIDX];
$tempNode = &$this->__xmlNodeArray[$childPtr];
return $tempNode->data;
}
function childDataNamed($tagName)
{
$retData "";
$holdPtr $this->currentPtr;
if ($this->stepInto($tagName)) 
{
$retData $this->currentData();
$this->currentPtr $holdPtr;
}
return $retData;
}
function &childNode($theIDX)
{
$retNode null;
$theNode = &$this->__xmlNodeArray[$this->currentPtr];
if (($theIDX >=0) and ($theIDX count($theNode->children)))
{
$ptr $theNode->children[$theIDX];
$retNode = &$this->__xmlNodeArray[$ptr];
}
return $retNode;
}
function childNodeNamed($tagName)
{
$retNode null;
$holdPtr $this->currentPtr;
if ($this->stepInto($tagName) )
{
$retNode = &$this->__xmlNodeArray[$this->currentPtr];
$this->currentPtr $holdPtr;
}
return $retNode;
}
function childTag($theIDX)
{
$tempNode = &$this->__xmlNodeArray[$this->currentPtr];
$childPtr $tempNode->children[$theIDX];
$tempNode = &$this->__xmlNodeArray[$childPtr];
return $tempNode->tag;
}
function clear()
{
$this->__xmlNodeArray = array();
$this->rootPtr $this->__newXMLNode();
$this->rootNode = &$this->__xmlNodeArray[0];