861 lines
21 KiB
PHP
861 lines
21 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* MiniXML - PHP class library for generating and parsing XML.
|
||
|
*
|
||
|
* @package miniXML
|
||
|
* @author Patrick Deegan, Psychogenic.com
|
||
|
* @license GPL
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
#define("MINIXML_COMPLETE_REGEX",'/<\s*([^\s>]+)([^>]+)?>(.*?)<\s*\/\\1\s*>\s*([^<]+)?(.*)|\s*<!--(.+?)-->\s*|^\s*<\s*([^\s>]+)([^>]*)\/\s*>\s*([^<>]+)?|<!\[CDATA\s*\[(.*?)\]\]\s*>|<!DOCTYPE\s*([^\[]*)\[(.*?)\]\s*>|<!ENTITY\s*([^"\'>]+)\s*(["\'])([^\14]+)\14\s*>|^([^<]+)(.*)/smi');
|
||
|
*/
|
||
|
|
||
|
define("MINIXML_COMPLETE_REGEX",'/^\s*<\s*([^\s>]+)(\s+[^>]+)?>(.*?)<\s*\/\1\s*>\s*([^<]+)?(.*)|^\s*<!--(.+?)-->\s*(.*)|^\s*<\s*([^\s>]+)([^>]+)\/\s*>\s*(.*)|^\s*<!\[CDATA\s*\[(.*?)\]\]\s*>\s*(.*)|^\s*<!DOCTYPE\s*([^\[]*)\[(.*?)\]\s*>\s*(.*)|^\s*<!ENTITY\s*([^"\'>]+)\s*(["\'])([^\17]+)\17\s*>\s*(.*)|^([^<]+)(.*)/smi');
|
||
|
|
||
|
/*
|
||
|
#define("MINIXML_SIMPLE_REGEX",
|
||
|
# // 1 2 3 4 5 6 7 8 9 #10 11
|
||
|
#'/\s*<\s*([^\s>]+)([^>]+)?>(.*?)<\s*\/\\1\s*>\s*([^<]+)?(.*)|\s*<!--(.+?)-->\s*|\s*<\s*([^\s>]+)([^>]*)\/\s*>\s*([^<>]+)?|^([^<]+)(.*)/smi');
|
||
|
|
||
|
*/
|
||
|
define("MINIXML_SIMPLE_REGEX",'/^\s*<\s*([^\s>]+)(\s+[^>]+)?>(.*?)<\s*\/\1\s*>\s*([^<]+)?(.*)|^\s*<!--(.+?)-->\s*(.*)|^\s*<\s*([^\s>]+)([^>]+)\/\s*>\s*(.*)|^([^<]+)(.*)/smi');
|
||
|
|
||
|
|
||
|
require_once(MINIXML_CLASSDIR . "/element.inc.php");
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
****************************************************************************************************
|
||
|
*****
|
||
|
***** MiniXMLDoc
|
||
|
*****
|
||
|
****************************************************************************************************
|
||
|
***************************************************************************************************/
|
||
|
|
||
|
/* MiniXMLDoc class
|
||
|
**
|
||
|
** The MiniXMLDoc class is the programmer's handle to MiniXML functionality.
|
||
|
**
|
||
|
** A MiniXMLDoc instance is created in every program that uses MiniXML.
|
||
|
** With the MiniXMLDoc object, you can access the root MiniXMLElement,
|
||
|
** find/fetch/create elements and read in or output XML strings.
|
||
|
**/
|
||
|
class MiniXMLDoc {
|
||
|
var $xxmlDoc;
|
||
|
var $xuseSimpleRegex;
|
||
|
var $xRegexIndex;
|
||
|
|
||
|
/* MiniXMLDoc [XMLSTRING]
|
||
|
** Constructor, create and init a MiniXMLDoc object.
|
||
|
**
|
||
|
** If the optional XMLSTRING is passed, the document will be initialised with
|
||
|
** a call to fromString using the XMLSTRING.
|
||
|
**
|
||
|
*/
|
||
|
function MiniXMLDoc ($string=NULL)
|
||
|
{
|
||
|
/* Set up the root element - note that it's name get's translated to a
|
||
|
** <? xml version="1.0" ?> string.
|
||
|
*/
|
||
|
$this->xxmlDoc = new MiniXMLElement("PSYCHOGENIC_ROOT_ELEMENT");
|
||
|
$this->xuseSimpleRegex = MINIXML_USE_SIMPLE;
|
||
|
if (! is_null($string))
|
||
|
{
|
||
|
$this->fromString($string);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function init ()
|
||
|
{
|
||
|
$this->xxmlDoc = new MiniXMLElement("PSYCHOGENIC_ROOT_ELEMENT");
|
||
|
}
|
||
|
|
||
|
/* getRoot
|
||
|
** Returns a reference the this document's root element
|
||
|
** (an instance of MiniXMLElement)
|
||
|
*/
|
||
|
function &getRoot ()
|
||
|
{
|
||
|
return $this->xxmlDoc;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* setRoot NEWROOT
|
||
|
** Set the document root to the NEWROOT MiniXMLElement object.
|
||
|
**/
|
||
|
function setRoot (&$root)
|
||
|
{
|
||
|
if ($this->isElement($root))
|
||
|
{
|
||
|
$this->xxmlDoc = $root;
|
||
|
} else {
|
||
|
return _MiniXMLError("MiniXMLDoc::setRoot(): Trying to set non-MiniXMLElement as root");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* isElement ELEMENT
|
||
|
** Returns a true value if ELEMENT is an instance of MiniXMLElement,
|
||
|
** false otherwise.
|
||
|
*/
|
||
|
function isElement (&$testme)
|
||
|
{
|
||
|
if (is_null($testme))
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return method_exists($testme, 'MiniXMLElement');
|
||
|
}
|
||
|
|
||
|
|
||
|
/* isNode NODE
|
||
|
** Returns a true value if NODE is an instance of MiniXMLNode,
|
||
|
** false otherwise.
|
||
|
*/
|
||
|
function isNode (&$testme)
|
||
|
{
|
||
|
if (is_null($testme))
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return method_exists($testme, 'MiniXMLNode');
|
||
|
}
|
||
|
|
||
|
|
||
|
/* createElement NAME [VALUE]
|
||
|
** Creates a new MiniXMLElement with name NAME.
|
||
|
** This element is an orphan (has no assigned parent)
|
||
|
** and will be lost unless it is appended (MiniXMLElement::appendChild())
|
||
|
** to an element at some point.
|
||
|
**
|
||
|
** If the optional VALUE (string or numeric) parameter is passed,
|
||
|
** the new element's text/numeric content will be set using VALUE.
|
||
|
**
|
||
|
** Returns a reference to the newly created element (use the =& operator)
|
||
|
*/
|
||
|
function &createElement ($name=NULL, $value=NULL)
|
||
|
{
|
||
|
$newElement = new MiniXMLElement($name);
|
||
|
|
||
|
if (! is_null($value))
|
||
|
{
|
||
|
if (is_numeric($value))
|
||
|
{
|
||
|
$newElement->numeric($value);
|
||
|
} elseif (is_string($value))
|
||
|
{
|
||
|
$newElement->text($value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $newElement;
|
||
|
}
|
||
|
|
||
|
/* getElement NAME
|
||
|
** Searches the document for an element with name NAME.
|
||
|
**
|
||
|
** Returns a reference to the first MiniXMLElement with name NAME,
|
||
|
** if found, NULL otherwise.
|
||
|
**
|
||
|
** NOTE: The search is performed like this, returning the first
|
||
|
** element that matches:
|
||
|
**
|
||
|
** - Check the Root Element's immediate children (in order) for a match.
|
||
|
** - Ask each immediate child (in order) to MiniXMLElement::getElement()
|
||
|
** (each child will then proceed similarly, checking all it's immediate
|
||
|
** children in order and then asking them to getElement())
|
||
|
*/
|
||
|
function &getElement ($name)
|
||
|
{
|
||
|
|
||
|
$element = $this->xxmlDoc->getElement($name);
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("MiniXMLDoc::getElement(): Returning element $element");
|
||
|
}
|
||
|
|
||
|
return $element;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/* getElementByPath PATH
|
||
|
** Attempts to return a reference to the (first) element at PATH
|
||
|
** where PATH is the path in the structure from the root element to
|
||
|
** the requested element.
|
||
|
**
|
||
|
** For example, in the document represented by:
|
||
|
**
|
||
|
** <partRateRequest>
|
||
|
** <vendor>
|
||
|
** <accessid user="myusername" password="mypassword" />
|
||
|
** </vendor>
|
||
|
** <partList>
|
||
|
** <partNum>
|
||
|
** DA42
|
||
|
** </partNum>
|
||
|
** <partNum>
|
||
|
** D99983FFF
|
||
|
** </partNum>
|
||
|
** <partNum>
|
||
|
** ss-839uent
|
||
|
** </partNum>
|
||
|
** </partList>
|
||
|
** </partRateRequest>
|
||
|
**
|
||
|
** $accessid =& $xmlDocument->getElementByPath('partRateRequest/vendor/accessid');
|
||
|
**
|
||
|
** Will return what you expect (the accessid element with attributes user = "myusername"
|
||
|
** and password = "mypassword").
|
||
|
**
|
||
|
** BUT be careful:
|
||
|
** $accessid =& $xmlDocument->getElementByPath('partRateRequest/partList/partNum');
|
||
|
**
|
||
|
** will return the partNum element with the value "DA42". Other partNums are
|
||
|
** inaccessible by getElementByPath() - Use MiniXMLElement::getAllChildren() instead.
|
||
|
**
|
||
|
** Returns the MiniXMLElement reference if found, NULL otherwise.
|
||
|
*/
|
||
|
function &getElementByPath ($path)
|
||
|
{
|
||
|
|
||
|
$element = $this->xxmlDoc->getElementByPath($path);
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("Returning element $element");
|
||
|
}
|
||
|
|
||
|
return $element;
|
||
|
|
||
|
}
|
||
|
|
||
|
function fromFile ($filename)
|
||
|
{
|
||
|
$modified = stat($filename);
|
||
|
if (! is_array($modified))
|
||
|
{
|
||
|
_MiniXMLError("Can't stat '$filename'");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (MINIXML_USEFROMFILECACHING > 0)
|
||
|
{
|
||
|
|
||
|
$tmpName = MINIXML_FROMFILECACHEDIR . '/' . 'minixml-' . md5($filename);
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("Trying to open cach file $tmpName (for '$filename')");
|
||
|
}
|
||
|
$cacheFileStat = stat($tmpName);
|
||
|
|
||
|
if (is_array($cacheFileStat) && $cacheFileStat[9] > $modified[9])
|
||
|
{
|
||
|
|
||
|
$fp = @fopen($tmpName,"r");
|
||
|
if ($fp)
|
||
|
{
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("Reading file '$filename' from object cache instead ($tmpName)");
|
||
|
}
|
||
|
$tmpFileSize = filesize($tmpName);
|
||
|
$tmpFileContents = fread($fp, $tmpFileSize);
|
||
|
|
||
|
$serializedObj = unserialize($tmpFileContents);
|
||
|
|
||
|
$sRoot =& $serializedObj->getRoot();
|
||
|
if ($sRoot)
|
||
|
{
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("Restoring object from cache file $tmpName");
|
||
|
}
|
||
|
$this->setRoot($sRoot);
|
||
|
|
||
|
/* Return immediately, such that we don't refresh the cache */
|
||
|
return $this->xxmlDoc->numChildren();
|
||
|
|
||
|
} /* end if we got a root element from unserialized object */
|
||
|
|
||
|
} /* end if we sucessfully opened the file */
|
||
|
|
||
|
|
||
|
} /* end if cache file exists and is more recent */
|
||
|
}
|
||
|
|
||
|
|
||
|
ob_start();
|
||
|
readfile($filename);
|
||
|
$filecontents = ob_get_contents();
|
||
|
ob_end_clean();
|
||
|
|
||
|
$retVal = $this->fromString($filecontents);
|
||
|
|
||
|
if (MINIXML_USEFROMFILECACHING > 0)
|
||
|
{
|
||
|
$this->saveToCache($filename);
|
||
|
}
|
||
|
|
||
|
return $retVal;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
function saveToCache ($filename)
|
||
|
{
|
||
|
$tmpName = MINIXML_FROMFILECACHEDIR . '/' . 'minixml-' . md5($filename);
|
||
|
|
||
|
$fp = @fopen($tmpName, "w");
|
||
|
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("Saving object to cache as '$tmpName'");
|
||
|
}
|
||
|
|
||
|
if ($fp)
|
||
|
{
|
||
|
|
||
|
$serialized = serialize($this);
|
||
|
fwrite($fp, $serialized);
|
||
|
|
||
|
fclose($fp);
|
||
|
} else {
|
||
|
_MiniXMLError("Could not open $tmpName for write in MiniXMLDoc::saveToCache()");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* fromString XMLSTRING
|
||
|
**
|
||
|
** Initialise the MiniXMLDoc (and it's root MiniXMLElement) using the
|
||
|
** XML string XMLSTRING.
|
||
|
**
|
||
|
** Returns the number of immediate children the root MiniXMLElement now
|
||
|
** has.
|
||
|
*/
|
||
|
function fromString (&$XMLString)
|
||
|
{
|
||
|
$useSimpleFlag = $this->xuseSimpleRegex;
|
||
|
|
||
|
|
||
|
if ($this->xuseSimpleRegex || ! preg_match('/<!DOCTYPE|<!ENTITY|<!\[CDATA/smi', $XMLString))
|
||
|
{
|
||
|
$this->xuseSimpleRegex = 1;
|
||
|
|
||
|
$this->xRegexIndex = array(
|
||
|
'biname' => 1,
|
||
|
'biattr' => 2,
|
||
|
'biencl' => 3,
|
||
|
'biendtxt' => 4,
|
||
|
'birest' => 5,
|
||
|
'comment' => 6,
|
||
|
'uname' => 8,
|
||
|
'uattr' => 9,
|
||
|
'plaintxt' => 11,
|
||
|
'plainrest' => 12
|
||
|
);
|
||
|
$regex = MINIXML_SIMPLE_REGEX;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
$this->xRegexIndex = array(
|
||
|
'biname' => 1,
|
||
|
'biattr' => 2,
|
||
|
'biencl' => 3,
|
||
|
'biendtxt' => 4,
|
||
|
'birest' => 5,
|
||
|
'comment' => 6,
|
||
|
'uname' => 8,
|
||
|
'uattr' => 9,
|
||
|
'cdata' => 11,
|
||
|
'doctypedef' => 13,
|
||
|
'doctypecont' => 14,
|
||
|
'entityname' => 16,
|
||
|
'entitydef' => 18,
|
||
|
'plaintxt' => 20,
|
||
|
'plainrest' => 21
|
||
|
);
|
||
|
$regex = MINIXML_COMPLETE_REGEX;
|
||
|
}
|
||
|
|
||
|
$this->fromSubString($this->xxmlDoc, $XMLString, $regex);
|
||
|
|
||
|
$this->xuseSimpleRegex = $useSimpleFlag;
|
||
|
|
||
|
return $this->xxmlDoc->numChildren();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
function fromArray (&$init, $params=NULL)
|
||
|
{
|
||
|
|
||
|
$this->init();
|
||
|
|
||
|
|
||
|
if (! is_array($init) )
|
||
|
{
|
||
|
|
||
|
return _MiniXMLError("MiniXMLDoc::fromArray(): Must Pass an ARRAY to initialize from");
|
||
|
}
|
||
|
|
||
|
if (! is_array($params) )
|
||
|
{
|
||
|
$params = array();
|
||
|
}
|
||
|
|
||
|
if ( $params["attributes"] && is_array($params["attributes"]) )
|
||
|
{
|
||
|
|
||
|
$attribs = array();
|
||
|
foreach ($params["attributes"] as $attribName => $value)
|
||
|
{
|
||
|
if (! (array_key_exists($attribName, $attribs) && is_array($attribs[$attribName]) ) )
|
||
|
{
|
||
|
$attribs[$attribName] = array();
|
||
|
}
|
||
|
|
||
|
if (is_array($value))
|
||
|
{
|
||
|
foreach ($value as $v)
|
||
|
{
|
||
|
if (array_key_exists($v, $attribs[$attribName]))
|
||
|
{
|
||
|
$attribs[$attribName][$v]++;
|
||
|
} else {
|
||
|
$attribs[$attribName][$v] = 1;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if (array_key_exists($value,$attribs[$attribName]))
|
||
|
{
|
||
|
$attribs[$attribName][$value]++;
|
||
|
} else {
|
||
|
$attribs[$attribName][$value] = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// completely replace old attributes by our optimized array
|
||
|
$params["attributes"] = $attribs;
|
||
|
} else {
|
||
|
$params["attributes"] = array();
|
||
|
}
|
||
|
|
||
|
foreach ($init as $keyname => $value)
|
||
|
{
|
||
|
$sub = $this->_fromArray_getExtractSub($value);
|
||
|
|
||
|
|
||
|
$this->$sub($keyname, $value, $this->xxmlDoc, $params);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
return $this->xxmlDoc->numChildren();
|
||
|
|
||
|
}
|
||
|
|
||
|
function _fromArray_getExtractSub ($v)
|
||
|
{
|
||
|
// is it a string, a numerical array or an associative array?
|
||
|
$sub = "_fromArray_extract";
|
||
|
if (is_array($v))
|
||
|
{
|
||
|
if (_MiniXML_NumKeyArray($v))
|
||
|
{
|
||
|
// All numeric - assume it is a "straight" array
|
||
|
$sub .= "ARRAY";
|
||
|
} else {
|
||
|
$sub .= "AssociativeARRAY";
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
$sub .= "STRING";
|
||
|
}
|
||
|
|
||
|
|
||
|
return $sub;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
function _fromArray_extractAssociativeARRAY ($name, &$value, &$parent, &$params)
|
||
|
{
|
||
|
|
||
|
$thisElement =& $parent->createChild($name);
|
||
|
|
||
|
foreach ($value as $key => $val)
|
||
|
{
|
||
|
|
||
|
$sub = $this->_fromArray_getExtractSub($val);
|
||
|
|
||
|
|
||
|
$this->$sub($key, $val, $thisElement, $params);
|
||
|
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
function _fromArray_extractARRAY ($name, &$value, &$parent, &$params)
|
||
|
{
|
||
|
|
||
|
foreach ($value as $val)
|
||
|
{
|
||
|
$sub = $this->_fromArray_getExtractSub($val);
|
||
|
|
||
|
|
||
|
$this->$sub($name, $val, $parent, $params);
|
||
|
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
function _fromArray_extractSTRING ($name, $value="", &$parent, &$params)
|
||
|
{
|
||
|
|
||
|
$pname = $parent->name();
|
||
|
|
||
|
if (
|
||
|
( array_key_exists($pname, $params['attributes']) && is_array($params['attributes'][$pname])
|
||
|
&& array_key_exists($name, $params['attributes'][$pname]) && $params['attributes'][$pname][$name])
|
||
|
|| (
|
||
|
array_key_exists('-all', $params['attributes']) && is_array($params['attributes']['-all'])
|
||
|
&& array_key_exists($name, $params['attributes']['-all']) && $params['attributes']['-all'][$name])
|
||
|
)
|
||
|
{
|
||
|
$parent->attribute($name, $value);
|
||
|
} elseif ($name == '-content') {
|
||
|
|
||
|
$parent->text($value);
|
||
|
} else {
|
||
|
$parent->createChild($name, $value);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
function time ($msg)
|
||
|
{
|
||
|
error_log("\nMiniXML msg '$msg', time: ". time() . "\n");
|
||
|
}
|
||
|
// fromSubString PARENTMINIXMLELEMENT XMLSUBSTRING
|
||
|
// private method, called recursively to parse the XMLString in little sub-chunks.
|
||
|
function fromSubString (&$parentElement, &$XMLString, &$regex)
|
||
|
{
|
||
|
//$this->time('fromSubStr');
|
||
|
|
||
|
if (is_null($parentElement) || empty($XMLString) || preg_match('/^\s*$/', $XMLString))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("Called fromSubString() with parent '" . $parentElement->name() . "'\n");
|
||
|
}
|
||
|
|
||
|
$matches = array();
|
||
|
if (preg_match_all( $regex, $XMLString, $matches))
|
||
|
{
|
||
|
// $this->time('a match');
|
||
|
|
||
|
$mcp = $matches;
|
||
|
|
||
|
$numMatches = count($mcp[0]);
|
||
|
|
||
|
for($i=0; $i < $numMatches; $i++)
|
||
|
{
|
||
|
if (MINIXML_DEBUG > 1)
|
||
|
{
|
||
|
_MiniXMLLog ("Got $numMatches CHECKING: ". $mcp[0][$i] . "\n");
|
||
|
}
|
||
|
|
||
|
$uname = $mcp[$this->xRegexIndex['uname']][$i];
|
||
|
$comment = $mcp[$this->xRegexIndex['comment']][$i];
|
||
|
if ($this->xuseSimpleRegex)
|
||
|
{
|
||
|
$cdata = NULL;
|
||
|
$doctypecont = NULL;
|
||
|
$entityname = NULL;
|
||
|
|
||
|
$tailEndIndexes = array(5, 7, 10, 12);
|
||
|
} else {
|
||
|
|
||
|
$cdata = $mcp[$this->xRegexIndex['cdata']][$i];
|
||
|
$doctypecont = $mcp[$this->xRegexIndex['doctypecont']][$i];
|
||
|
$entityname = $mcp[$this->xRegexIndex['entityname']][$i];
|
||
|
|
||
|
$tailEndIndexes = array(5, 7, 10, 12, 15, 19, 21);
|
||
|
}
|
||
|
|
||
|
$plaintext = $mcp[$this->xRegexIndex['plaintxt']][$i];
|
||
|
|
||
|
// check all the 'tailend' (i.e. rest of string) matches for more content
|
||
|
$moreContent = '';
|
||
|
$idx = 0;
|
||
|
while (empty($moreContent) && ($idx < count($tailEndIndexes)))
|
||
|
{
|
||
|
if (! empty($mcp[$tailEndIndexes[$idx]][$i]))
|
||
|
{
|
||
|
$moreContent = $mcp[$tailEndIndexes[$idx]][$i];
|
||
|
}
|
||
|
|
||
|
$idx++;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
if ($uname)
|
||
|
{
|
||
|
// _MiniXMLLog ("Got UNARY $uname");
|
||
|
$newElement =& $parentElement->createChild($uname);
|
||
|
$this->_extractAttributesFromString($newElement, $mcp[$this->xRegexIndex['uattr']][$i]);
|
||
|
|
||
|
} elseif ($comment) {
|
||
|
//_MiniXMLLog ("Got comment $comment");
|
||
|
$parentElement->comment($comment);
|
||
|
|
||
|
} elseif ($cdata) {
|
||
|
//_MiniXMLLog ("Got cdata $cdata");
|
||
|
$newElement = new MiniXMLElementCData($cdata);
|
||
|
$parentElement->appendChild($newElement);
|
||
|
} elseif ($doctypecont) {
|
||
|
//_MiniXMLLog ("Got doctype $doctypedef '" . $mcp[11][$i] . "'");
|
||
|
$newElement = new MiniXMLElementDocType($mcp[$this->xRegexIndex['doctypedef']][$i]);
|
||
|
$appendedChild =& $parentElement->appendChild($newElement);
|
||
|
$this->fromSubString($appendedChild, $doctypecont, $regex);
|
||
|
|
||
|
} elseif ($entityname ) {
|
||
|
//_MiniXMLLog ("Got entity $entityname");
|
||
|
$newElement = new MiniXMLElementEntity ($entityname, $mcp[$this->xRegexIndex['entitydef']][$i]);
|
||
|
$parentElement->appendChild($newElement);
|
||
|
|
||
|
} elseif ($plaintext) {
|
||
|
|
||
|
if (! preg_match('/^\s+$/', $plaintext))
|
||
|
{
|
||
|
$parentElement->createNode($plaintext);
|
||
|
}
|
||
|
|
||
|
} elseif($mcp[$this->xRegexIndex['biname']]) {
|
||
|
|
||
|
// _MiniXMLLog("Got BIN NAME: " . $mcp[$this->xRegexIndex['biname']][$i]);
|
||
|
|
||
|
$nencl = $mcp[$this->xRegexIndex['biencl']][$i];
|
||
|
$finaltxt = $mcp[$this->xRegexIndex['biendtxt']][$i];
|
||
|
|
||
|
$newElement =& $parentElement->createChild($mcp[$this->xRegexIndex['biname']][$i]);
|
||
|
$this->_extractAttributesFromString($newElement, $mcp[$this->xRegexIndex['biattr']][$i]);
|
||
|
|
||
|
|
||
|
|
||
|
$plaintxtMatches = array();
|
||
|
if (preg_match("/^\s*([^\s<][^<]*)/", $nencl, $plaintxtMatches))
|
||
|
{
|
||
|
$txt = $plaintxtMatches[1];
|
||
|
$newElement->createNode($txt);
|
||
|
|
||
|
$nencl = preg_replace("/^\s*([^<]+)/", "", $nencl);
|
||
|
}
|
||
|
|
||
|
|
||
|
if ($nencl && !preg_match('/^\s*$/', $nencl))
|
||
|
{
|
||
|
$this->fromSubString($newElement, $nencl, $regex);
|
||
|
}
|
||
|
|
||
|
if ($finaltxt)
|
||
|
{
|
||
|
$parentElement->createNode($finaltxt);
|
||
|
}
|
||
|
|
||
|
|
||
|
} /* end switch over type of match */
|
||
|
|
||
|
if (! empty($moreContent))
|
||
|
{
|
||
|
$this->fromSubString($parentElement, $moreContent, $regex);
|
||
|
}
|
||
|
|
||
|
|
||
|
} /* end loop over all matches */
|
||
|
|
||
|
|
||
|
} /* end if there was a match */
|
||
|
|
||
|
} /* end method fromSubString */
|
||
|
|
||
|
|
||
|
/* toString [DEPTH]
|
||
|
** Converts this MiniXMLDoc object to a string and returns it.
|
||
|
**
|
||
|
** The optional DEPTH may be passed to set the space offset for the
|
||
|
** first element.
|
||
|
**
|
||
|
** If the optional DEPTH is set to MINIXML_NOWHITESPACES.
|
||
|
** When it is, no \n or whitespaces will be inserted in the xml string
|
||
|
** (ie it will all be on a single line with no spaces between the tags.
|
||
|
**
|
||
|
** Returns a string of XML representing the document.
|
||
|
*/
|
||
|
function toString ($depth=0)
|
||
|
{
|
||
|
$retString = $this->xxmlDoc->toString($depth);
|
||
|
|
||
|
if ($depth == MINIXML_NOWHITESPACES)
|
||
|
{
|
||
|
$xmlhead = "<?xml version=\"1.0\"\\1?>";
|
||
|
} else {
|
||
|
$xmlhead = "<?xml version=\"1.0\"\\1?>\n ";
|
||
|
}
|
||
|
$search = array("/<PSYCHOGENIC_ROOT_ELEMENT([^>]*)>\s*/smi",
|
||
|
"/<\/PSYCHOGENIC_ROOT_ELEMENT>/smi");
|
||
|
$replace = array($xmlhead,
|
||
|
"");
|
||
|
$retString = preg_replace($search, $replace, $retString);
|
||
|
|
||
|
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("MiniXML::toString() Returning XML:\n$retString\n\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* toArray
|
||
|
**
|
||
|
** Transforms the XML structure currently represented by the MiniXML Document object
|
||
|
** into an array.
|
||
|
**
|
||
|
** More docs to come - for the moment, use var_dump($miniXMLDoc->toArray()) to see
|
||
|
** what's going on :)
|
||
|
*/
|
||
|
|
||
|
function & toArray ()
|
||
|
{
|
||
|
|
||
|
$retVal = $this->xxmlDoc->toStructure();
|
||
|
|
||
|
if (is_array($retVal))
|
||
|
{
|
||
|
return $retVal;
|
||
|
}
|
||
|
|
||
|
$retArray = array(
|
||
|
'-content' => $retVal,
|
||
|
);
|
||
|
|
||
|
return $retArray;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* getValue()
|
||
|
** Utility function, call the root MiniXMLElement's getValue()
|
||
|
*/
|
||
|
function getValue ()
|
||
|
{
|
||
|
return $this->xxmlDoc->getValue();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* dump
|
||
|
** Debugging aid, dump returns a nicely formatted dump of the current structure of the
|
||
|
** MiniXMLDoc object.
|
||
|
*/
|
||
|
function dump ()
|
||
|
{
|
||
|
return serialize($this);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// _extractAttributesFromString
|
||
|
// private method for extracting and setting the attributs from a
|
||
|
// ' a="b" c = "d"' string
|
||
|
function _extractAttributesFromString (&$element, &$attrString)
|
||
|
{
|
||
|
|
||
|
if (! $attrString)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
$count = 0;
|
||
|
$attribs = array();
|
||
|
// Set the attribs
|
||
|
preg_match_all('/([^\s]+)\s*=\s*([\'"])([^\2]*?)\2/sm', $attrString, $attribs);
|
||
|
|
||
|
|
||
|
for ($i = 0; $i < count($attribs[0]); $i++)
|
||
|
{
|
||
|
$attrname = $attribs[1][$i];
|
||
|
$attrval = $attribs[3][$i];
|
||
|
|
||
|
if ($attrname)
|
||
|
{
|
||
|
$element->attribute($attrname, $attrval, '');
|
||
|
$count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $count;
|
||
|
}
|
||
|
|
||
|
/* Destructor to keep things clean -- patch by Ilya */
|
||
|
function __destruct()
|
||
|
{
|
||
|
$this->xxmlDoc = null;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
****************************************************************************************************
|
||
|
*****
|
||
|
***** MiniXML
|
||
|
*****
|
||
|
****************************************************************************************************
|
||
|
***************************************************************************************************/
|
||
|
|
||
|
/* class MiniXML (MiniXMLDoc)
|
||
|
**
|
||
|
** Avoid using me - I involve needless overhead.
|
||
|
**
|
||
|
** Utility class - this is just an name aliase for the
|
||
|
** MiniXMLDoc class as I keep repeating the mistake of
|
||
|
** trying to create
|
||
|
**
|
||
|
** $xml = new MiniXML();
|
||
|
**
|
||
|
*/
|
||
|
class MiniXML extends MiniXMLDoc {
|
||
|
|
||
|
function MiniXML ()
|
||
|
{
|
||
|
$this->MiniXMLDoc();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
?>
|