1729 lines
40 KiB
PHP
1729 lines
40 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* MiniXML - PHP class library for generating and parsing XML.
|
||
|
*
|
||
|
* @package miniXML
|
||
|
* @author Patrick Deegan, Psychogenic.com
|
||
|
* @license GPL
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
require_once(MINIXML_CLASSDIR . "/treecomp.inc.php");
|
||
|
require_once(MINIXML_CLASSDIR . "/node.inc.php");
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
****************************************************************************************************
|
||
|
*****
|
||
|
***** MiniXMLElement
|
||
|
*****
|
||
|
****************************************************************************************************
|
||
|
***************************************************************************************************/
|
||
|
|
||
|
|
||
|
/* class MiniXMLElement (MiniXMLTreeComponent)
|
||
|
**
|
||
|
** Although the main handle to the xml document is the MiniXMLDoc object,
|
||
|
** much of the functionality and manipulation involves interaction with
|
||
|
** MiniXMLElement objects.
|
||
|
**
|
||
|
** A MiniXMLElement
|
||
|
** has:
|
||
|
** - a name
|
||
|
** - a list of 0 or more attributes (which have a name and a value)
|
||
|
** - a list of 0 or more children (MiniXMLElement or MiniXMLNode objects)
|
||
|
** - a parent (optional, only if MINIXML_AUTOSETPARENT > 0)
|
||
|
**/
|
||
|
|
||
|
class MiniXMLElement extends MiniXMLTreeComponent {
|
||
|
|
||
|
|
||
|
var $xname;
|
||
|
var $xattributes;
|
||
|
var $xchildren;
|
||
|
var $xnumChildren;
|
||
|
var $xnumElementChildren;
|
||
|
|
||
|
var $xavoidLoops = MINIXML_AVOIDLOOPS;
|
||
|
|
||
|
|
||
|
/* MiniXMLElement NAME
|
||
|
** Creates and inits a new MiniXMLElement
|
||
|
*/
|
||
|
function MiniXMLElement ($name=NULL)
|
||
|
{
|
||
|
$this->MiniXMLTreeComponent();
|
||
|
$this->xname = NULL;
|
||
|
$this->xattributes = array();
|
||
|
$this->xchildren = array();
|
||
|
$this->xnumChildren = 0;
|
||
|
$this->xnumElementChildren = 0;
|
||
|
if ($name)
|
||
|
{
|
||
|
$this->name($name);
|
||
|
} else {
|
||
|
return _MiniXMLError("MiniXMLElement Constructor: must pass a name to constructor");
|
||
|
}
|
||
|
} /* end method MiniXMLElement */
|
||
|
|
||
|
|
||
|
/**************** Get/set methods for MiniXMLElement data *****************/
|
||
|
|
||
|
|
||
|
/* name [NEWNAME]
|
||
|
**
|
||
|
** If a NEWNAME string is passed, the MiniXMLElement's name is set
|
||
|
** to NEWNAME.
|
||
|
**
|
||
|
** Returns the element's name.
|
||
|
*/
|
||
|
function name ($setTo=NULL)
|
||
|
{
|
||
|
if (! is_null($setTo))
|
||
|
{
|
||
|
if (! is_string($setTo))
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::name() Must pass a STRING to method to set name");
|
||
|
}
|
||
|
|
||
|
$this->xname = $setTo;
|
||
|
}
|
||
|
|
||
|
return $this->xname;
|
||
|
|
||
|
} /* end method name */
|
||
|
|
||
|
|
||
|
|
||
|
/* attribute NAME [SETTO [SETTOALT]]
|
||
|
**
|
||
|
** The attribute() method is used to get and set the
|
||
|
** MiniXMLElement's attributes (ie the name/value pairs contained
|
||
|
** within the tag, <tagname attrib1="value1" attrib2="value2">)
|
||
|
**
|
||
|
** If SETTO is passed, the attribute's value is set to SETTO.
|
||
|
**
|
||
|
** If the optional SETTOALT is passed and SETTO is false, the
|
||
|
** attribute's value is set to SETTOALT. This is usefull in cases
|
||
|
** when you wish to set the attribute to a default value if no SETTO is
|
||
|
** present, eg $myelement->attribute('href', $theHref, 'http://psychogenic.com')
|
||
|
** will default to 'http://psychogenic.com'.
|
||
|
**
|
||
|
** Note: if the MINIXML_LOWERCASEATTRIBUTES define is > 0, all attribute names
|
||
|
** will be lowercased (while setting and during retrieval)
|
||
|
**
|
||
|
** Returns the value associated with attribute NAME.
|
||
|
**
|
||
|
*/
|
||
|
function attribute ($name, $primValue=NULL, $altValue=NULL)
|
||
|
{
|
||
|
$value = (is_null($primValue) ? $altValue : $primValue );
|
||
|
|
||
|
|
||
|
if (MINIXML_UPPERCASEATTRIBUTES > 0)
|
||
|
{
|
||
|
$name = strtoupper($name);
|
||
|
} elseif (MINIXML_LOWERCASEATTRIBUTES > 0)
|
||
|
{
|
||
|
$name = strtolower($name);
|
||
|
}
|
||
|
|
||
|
if (! is_null($value))
|
||
|
{
|
||
|
|
||
|
$this->xattributes[$name] = $value;
|
||
|
}
|
||
|
|
||
|
if (! is_null($this->xattributes[$name]))
|
||
|
{
|
||
|
return $this->xattributes[$name];
|
||
|
} else {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
} /* end method attribute */
|
||
|
|
||
|
|
||
|
/* text [SETTO [SETTOALT]]
|
||
|
**
|
||
|
** The text() method is used to get or append text data to this
|
||
|
** element (it is appended to the child list as a new MiniXMLNode object).
|
||
|
**
|
||
|
** If SETTO is passed, a new node is created, filled with SETTO
|
||
|
** and appended to the list of this element's children.
|
||
|
**
|
||
|
** If the optional SETTOALT is passed and SETTO is false, the
|
||
|
** new node's value is set to SETTOALT. See the attribute() method
|
||
|
** for an example use.
|
||
|
**
|
||
|
** Returns a string composed of all child MiniXMLNodes' contents.
|
||
|
**
|
||
|
** Note: all the children MiniXMLNodes' contents - including numeric
|
||
|
** nodes are included in the return string.
|
||
|
*/
|
||
|
function text ($setToPrimary = NULL, $setToAlternate=NULL)
|
||
|
{
|
||
|
$setTo = ($setToPrimary ? $setToPrimary : $setToAlternate);
|
||
|
|
||
|
if (! is_null($setTo))
|
||
|
{
|
||
|
$this->createNode($setTo);
|
||
|
}
|
||
|
|
||
|
$retString = '';
|
||
|
|
||
|
/* Extract text from all child nodes */
|
||
|
for($i=0; $i< $this->xnumChildren; $i++)
|
||
|
{
|
||
|
if ($this->isNode($this->xchildren[$i]))
|
||
|
{
|
||
|
$nodeTxt = $this->xchildren[$i]->getValue();
|
||
|
if (! is_null($nodeTxt))
|
||
|
{
|
||
|
$retString .= "$nodeTxt ";
|
||
|
|
||
|
} /* end if text returned */
|
||
|
|
||
|
} /* end if this is a MiniXMLNode */
|
||
|
|
||
|
} /* end loop over all children */
|
||
|
|
||
|
return $retString;
|
||
|
|
||
|
} /* end method text */
|
||
|
|
||
|
|
||
|
|
||
|
/* numeric [SETTO [SETTOALT]]
|
||
|
**
|
||
|
** The numeric() method is used to get or append numeric data to
|
||
|
** this element (it is appended to the child list as a MiniXMLNode object).
|
||
|
**
|
||
|
** If SETTO is passed, a new node is created, filled with SETTO
|
||
|
** and appended to the list of this element's children.
|
||
|
**
|
||
|
** If the optional SETTOALT is passed and SETTO is false, the
|
||
|
** new node's value is set to SETTOALT. See the attribute() method
|
||
|
** for an example use.
|
||
|
**
|
||
|
** Returns a space seperated string composed all child MiniXMLNodes'
|
||
|
** numeric contents.
|
||
|
**
|
||
|
** Note: ONLY numerical contents are included from the list of child MiniXMLNodes.
|
||
|
**
|
||
|
*/
|
||
|
function numeric ($setToPrimary = NULL, $setToAlternate=NULL)
|
||
|
{
|
||
|
$setTo = (is_null($setToPrimary) ? $setToAlternate : $setToPrimary);
|
||
|
|
||
|
if (! is_null($setTo))
|
||
|
{
|
||
|
$this->createNode($setTo);
|
||
|
}
|
||
|
|
||
|
} /* end method numeric */
|
||
|
|
||
|
|
||
|
/* comment CONTENTS
|
||
|
**
|
||
|
** The comment() method allows you to add a new MiniXMLElementComment to this
|
||
|
** element's list of children.
|
||
|
**
|
||
|
** Comments will return a <!-- CONTENTS --> string when the element's toString()
|
||
|
** method is called.
|
||
|
**
|
||
|
** Returns a reference to the newly appended MiniXMLElementComment
|
||
|
**
|
||
|
*/
|
||
|
function & comment ($contents)
|
||
|
{
|
||
|
$newEl = new MiniXMLElementComment();
|
||
|
|
||
|
$appendedComment =& $this->appendChild($newEl);
|
||
|
$appendedComment->text($contents);
|
||
|
|
||
|
return $appendedComment;
|
||
|
|
||
|
} /* end method comment */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
** docType DEFINITION
|
||
|
**
|
||
|
** Append a new <!DOCTYPE DEFINITION [ ...]> element as a child of this
|
||
|
** element.
|
||
|
**
|
||
|
** Returns the appended DOCTYPE element. You will normally use the returned
|
||
|
** element to add ENTITY elements, like
|
||
|
|
||
|
** $newDocType =& $xmlRoot->docType('spec SYSTEM "spec.dtd"');
|
||
|
** $newDocType->entity('doc.audience', 'public review and discussion');
|
||
|
*/
|
||
|
|
||
|
function & docType ($definition)
|
||
|
{
|
||
|
|
||
|
$newElement = new MiniXMLElementDocType($definition);
|
||
|
$appendedElement =& $this->appendChild($newElement);
|
||
|
|
||
|
return $appendedElement;
|
||
|
}
|
||
|
/*
|
||
|
** entity NAME VALUE
|
||
|
**
|
||
|
** Append a new <!ENTITY NAME "VALUE"> element as a child of this
|
||
|
** element.
|
||
|
|
||
|
** Returns the appended ENTITY element.
|
||
|
*/
|
||
|
function & entity ($name,$value)
|
||
|
{
|
||
|
|
||
|
$newElement = new MiniXMLElementEntity($name, $value);
|
||
|
$appendedEl =& $this->appendChild($newElement);
|
||
|
|
||
|
return $appendedEl;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
** cdata CONTENTS
|
||
|
**
|
||
|
** Append a new <![CDATA[ CONTENTS ]]> element as a child of this element.
|
||
|
** Returns the appended CDATA element.
|
||
|
**
|
||
|
*/
|
||
|
|
||
|
function & cdata ($contents)
|
||
|
{
|
||
|
$newElement = new MiniXMLElementCData($contents);
|
||
|
$appendedChild =& $this->appendChild($newElement);
|
||
|
|
||
|
return $appendedChild;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* getValue
|
||
|
**
|
||
|
** Returns a string containing the value of all the element's
|
||
|
** child MiniXMLNodes (and all the MiniXMLNodes contained within
|
||
|
** it's child MiniXMLElements, recursively).
|
||
|
**
|
||
|
** Note: the seperator parameter remains officially undocumented
|
||
|
** since I'm not sure it will remain part of the API
|
||
|
*/
|
||
|
function getValue ($seperator=' ')
|
||
|
{
|
||
|
$retStr = '';
|
||
|
$valArray = array();
|
||
|
for($i=0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
$value = $this->xchildren[$i]->getValue();
|
||
|
if (! is_null($value))
|
||
|
{
|
||
|
array_push($valArray, $value);
|
||
|
}
|
||
|
}
|
||
|
if (count($valArray))
|
||
|
{
|
||
|
$retStr = implode($seperator, $valArray);
|
||
|
}
|
||
|
return $retStr;
|
||
|
|
||
|
} /* end method getValue */
|
||
|
|
||
|
|
||
|
|
||
|
/* getElement NAME
|
||
|
** Searches the element and it's children 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 this element for a match
|
||
|
** - Check this 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)
|
||
|
{
|
||
|
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
$elname = $this->name();
|
||
|
_MiniXMLLog("MiniXMLElement::getElement() called for $name on $elname.");
|
||
|
}
|
||
|
if (is_null($name))
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::getElement() Must Pass Element name.");
|
||
|
}
|
||
|
|
||
|
|
||
|
/** Must only check children as checking $this results in an inability to
|
||
|
*** fetch nested objects with the same name
|
||
|
*** <tag>
|
||
|
*** <nested>
|
||
|
*** <nested>
|
||
|
*** Can't get here from tag or from the first 'nested'
|
||
|
*** </nested>
|
||
|
*** </nested>
|
||
|
*** </tag>
|
||
|
if (MINIXML_CASESENSITIVE > 0)
|
||
|
{
|
||
|
if (strcmp($this->xname, $name) == 0)
|
||
|
{
|
||
|
/* This element is it * /
|
||
|
return $this;
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
if (strcasecmp($this->xname,$name) == 0)
|
||
|
{
|
||
|
return $this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
***** end commented out section ****
|
||
|
*/
|
||
|
|
||
|
if (! $this->xnumChildren )
|
||
|
{
|
||
|
/* Not match here and and no kids - not found... */
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Try each child (immediate children take priority) */
|
||
|
for ($i = 0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
$childname = $this->xchildren[$i]->name();
|
||
|
if ($childname)
|
||
|
{
|
||
|
if (MINIXML_CASESENSITIVE > 0)
|
||
|
{
|
||
|
/* case sensitive matches only */
|
||
|
if (strcmp($name, $childname) == 0)
|
||
|
{
|
||
|
return $this->xchildren[$i];
|
||
|
}
|
||
|
} else {
|
||
|
/* case INsensitive matching */
|
||
|
if (strcasecmp($name, $childname) == 0)
|
||
|
{
|
||
|
return $this->xchildren[$i];
|
||
|
}
|
||
|
} /* end if case sensitive */
|
||
|
} /* end if child has a name */
|
||
|
|
||
|
} /* end loop over all my children */
|
||
|
|
||
|
/* Use beautiful recursion, daniel san */
|
||
|
for ($i = 0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
$theelement =& $this->xchildren[$i]->getElement($name);
|
||
|
if ($theelement)
|
||
|
{
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("MiniXMLElement::getElement() returning element $theelement");
|
||
|
}
|
||
|
return $theelement;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Not found */
|
||
|
return NULL;
|
||
|
|
||
|
|
||
|
} /* end method getElement */
|
||
|
|
||
|
|
||
|
/* getElementByPath PATH
|
||
|
** Attempts to return a reference to the (first) element at PATH
|
||
|
** where PATH is the path in the structure (relative to this 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>
|
||
|
**
|
||
|
** $partRate =& $xmlDocument->getElement('partRateRequest');
|
||
|
**
|
||
|
** $accessid =& $partRate->getElementByPath('vendor/accessid');
|
||
|
**
|
||
|
** Will return what you expect (the accessid element with attributes user = "myusername"
|
||
|
** and password = "mypassword").
|
||
|
**
|
||
|
** BUT be careful:
|
||
|
** $accessid =& $partRate->getElementByPath('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)
|
||
|
{
|
||
|
$names = split ("/", $path);
|
||
|
|
||
|
$element = $this;
|
||
|
foreach ($names as $elementName)
|
||
|
{
|
||
|
if ($element && $elementName) /* Make sure we didn't hit a dead end and that we have a name*/
|
||
|
{
|
||
|
/* Ask this element to get the next child in path */
|
||
|
$element =& $element->getElement($elementName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $element;
|
||
|
|
||
|
} /* end method getElementByPath */
|
||
|
|
||
|
|
||
|
|
||
|
/* numChildren [NAMED]
|
||
|
**
|
||
|
** Returns the number of immediate children for this element
|
||
|
**
|
||
|
** If the optional NAMED parameter is passed, returns only the
|
||
|
** number of immediate children named NAMED.
|
||
|
*/
|
||
|
function numChildren ($named=NULL)
|
||
|
{
|
||
|
if (is_null($named))
|
||
|
{
|
||
|
return $this->xnumElementChildren;
|
||
|
}
|
||
|
|
||
|
/* We require only children named '$named' */
|
||
|
$allkids =& $this->getAllChildren($named);
|
||
|
|
||
|
return count($allkids);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/* getAllChildren [NAME]
|
||
|
**
|
||
|
** Returns a reference to an array of all this element's MiniXMLElement children
|
||
|
**
|
||
|
** Note: although the MiniXMLElement may contain MiniXMLNodes as children, these are
|
||
|
** not part of the returned list.
|
||
|
**/
|
||
|
function &getAllChildren ($name=NULL)
|
||
|
{
|
||
|
$retArray = array();
|
||
|
$count = 0;
|
||
|
|
||
|
if (is_null($name))
|
||
|
{
|
||
|
/* Return all element children */
|
||
|
for($i=0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
if (method_exists($this->xchildren[$i], 'MiniXMLElement'))
|
||
|
{
|
||
|
$retArray[$count++] =& $this->xchildren[$i];
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
/* Return only element children with name $name */
|
||
|
|
||
|
for($i=0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
if (method_exists($this->xchildren[$i], 'MiniXMLElement'))
|
||
|
{
|
||
|
if (MINIXML_CASESENSITIVE > 0)
|
||
|
{
|
||
|
if ($this->xchildren[$i]->name() == $name)
|
||
|
{
|
||
|
$retArray[$count++] =& $this->xchildren[$i];
|
||
|
}
|
||
|
} else {
|
||
|
if (strcasecmp($this->xchildren[$i]->name(), $name) == 0)
|
||
|
{
|
||
|
$retArray[$count++] =& $this->xchildren[$i];
|
||
|
}
|
||
|
} /* end if case sensitive */
|
||
|
|
||
|
} /* end if child is a MiniXMLElement object */
|
||
|
|
||
|
} /* end loop over all children */
|
||
|
|
||
|
} /* end if specific name was requested */
|
||
|
|
||
|
return $retArray;
|
||
|
|
||
|
} /* end method getAllChildren */
|
||
|
|
||
|
|
||
|
|
||
|
function &insertChild (&$child, $idx=0)
|
||
|
{
|
||
|
|
||
|
|
||
|
|
||
|
if (! $this->_validateChild($child))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Set the parent for the child element to this element if
|
||
|
** avoidLoops or MINIXML_AUTOSETPARENT is set
|
||
|
*/
|
||
|
if ($this->xavoidLoops || (MINIXML_AUTOSETPARENT > 0) )
|
||
|
{
|
||
|
if ($this->xparent == $child)
|
||
|
{
|
||
|
|
||
|
$cname = $child->name();
|
||
|
return _MiniXMLError("MiniXMLElement::insertChild() Tryng to append parent $cname as child of "
|
||
|
. $this->xname );
|
||
|
}
|
||
|
$child->parent($this);
|
||
|
}
|
||
|
|
||
|
|
||
|
$nextIdx = $this->xnumChildren;
|
||
|
$lastIdx = $nextIdx - 1;
|
||
|
if ($idx > $lastIdx)
|
||
|
{
|
||
|
|
||
|
if ($idx > $nextIdx)
|
||
|
{
|
||
|
$idx = $lastIdx + 1;
|
||
|
}
|
||
|
$this->xchildren[$idx] = $child;
|
||
|
$this->xnumChildren++;
|
||
|
if ($this->isElement($child))
|
||
|
{
|
||
|
$this->xnumElementChildren++;
|
||
|
}
|
||
|
|
||
|
} elseif ($idx >= 0)
|
||
|
{
|
||
|
|
||
|
$removed = array_splice($this->xchildren, $idx);
|
||
|
array_push($this->xchildren, $child);
|
||
|
$numRemoved = count($removed);
|
||
|
|
||
|
for($i=0; $i<$numRemoved; $i++)
|
||
|
{
|
||
|
|
||
|
array_push($this->xchildren, $removed[$i]);
|
||
|
}
|
||
|
$this->xnumChildren++;
|
||
|
if ($this->isElement($child))
|
||
|
{
|
||
|
$this->xnumElementChildren++;
|
||
|
}
|
||
|
|
||
|
|
||
|
} else {
|
||
|
$revIdx = (-1 * $idx) % $this->xnumChildren;
|
||
|
$newIdx = $this->xnumChildren - $revIdx;
|
||
|
|
||
|
if ($newIdx < 0)
|
||
|
{
|
||
|
return _MiniXMLError("Element::insertChild() Ended up with a negative index? ($newIdx)");
|
||
|
}
|
||
|
|
||
|
return $this->insertChild($child, $newIdx);
|
||
|
}
|
||
|
|
||
|
return $child;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* appendChild CHILDELEMENT
|
||
|
**
|
||
|
** appendChild is used to append an existing MiniXMLElement object to
|
||
|
** this element's list.
|
||
|
**
|
||
|
** Returns a reference to the appended child element.
|
||
|
**
|
||
|
** NOTE: Be careful not to create loops in the hierarchy, eg
|
||
|
** $parent->appendChild($child);
|
||
|
** $child->appendChild($subChild);
|
||
|
** $subChild->appendChild($parent);
|
||
|
**
|
||
|
** If you want to be sure to avoid loops, set the MINIXML_AVOIDLOOPS define
|
||
|
** to 1 or use the avoidLoops() method (will apply to all children added with createChild())
|
||
|
*/
|
||
|
function &appendChild (&$child)
|
||
|
{
|
||
|
|
||
|
if (! $this->_validateChild($child))
|
||
|
{
|
||
|
_MiniXMLLog("MiniXMLElement::appendChild() Could not validate child, aborting append");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Set the parent for the child element to this element if
|
||
|
** avoidLoops or MINIXML_AUTOSETPARENT is set
|
||
|
*/
|
||
|
if ($this->xavoidLoops || (MINIXML_AUTOSETPARENT > 0) )
|
||
|
{
|
||
|
if ($this->xparent == $child)
|
||
|
{
|
||
|
|
||
|
$cname = $child->name();
|
||
|
return _MiniXMLError("MiniXMLElement::appendChild() Tryng to append parent $cname as child of "
|
||
|
. $this->xname );
|
||
|
}
|
||
|
$child->parent($this);
|
||
|
}
|
||
|
|
||
|
|
||
|
$this->xnumElementChildren++; /* Note that we're addind a MiniXMLElement child */
|
||
|
|
||
|
/* Add the child to the list */
|
||
|
$idx = $this->xnumChildren++;
|
||
|
$this->xchildren[$idx] =& $child;
|
||
|
|
||
|
return $this->xchildren[$idx];
|
||
|
|
||
|
} /* end method appendChild */
|
||
|
|
||
|
|
||
|
/* prependChild CHILDELEMENT
|
||
|
**
|
||
|
** prependChild is used to prepend an existing MiniXMLElement object to
|
||
|
** this element's list. The child will be positioned at the begining of
|
||
|
** the elements child list, thus it will be output first in the resulting XML.
|
||
|
**
|
||
|
** Returns a reference to the prepended child element.
|
||
|
*/
|
||
|
function &prependChild ($child)
|
||
|
{
|
||
|
|
||
|
|
||
|
if (! $this->_validateChild($child))
|
||
|
{
|
||
|
_MiniXMLLog("MiniXMLElement::prependChild - Could not validate child, aborting.");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Set the parent for the child element to this element if
|
||
|
** avoidLoops or MINIXML_AUTOSETPARENT is set
|
||
|
*/
|
||
|
if ($this->xavoidLoops || (MINIXML_AUTOSETPARENT > 0) )
|
||
|
{
|
||
|
if ($this->xparent == $child)
|
||
|
{
|
||
|
|
||
|
$cname = $child->name();
|
||
|
return _MiniXMLError("MiniXMLElement::prependChild() Tryng to append parent $cname as child of "
|
||
|
. $this->xname );
|
||
|
}
|
||
|
$child->parent($this);
|
||
|
}
|
||
|
|
||
|
|
||
|
$this->xnumElementChildren++; /* Note that we're adding a MiniXMLElement child */
|
||
|
|
||
|
/* Add the child to the list */
|
||
|
$idx = $this->xnumChildren++;
|
||
|
array_unshift($this->xchildren, $child);
|
||
|
return $this->xchildren[0];
|
||
|
|
||
|
} /* end method prependChild */
|
||
|
|
||
|
function _validateChild (&$child)
|
||
|
{
|
||
|
|
||
|
if (is_null($child))
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::_validateChild() need to pass a non-NULL MiniXMLElement child.");
|
||
|
}
|
||
|
|
||
|
if (! method_exists($child, 'MiniXMLElement'))
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::_validateChild() must pass a MiniXMLElement object to _validateChild.");
|
||
|
}
|
||
|
|
||
|
/* Make sure element is named */
|
||
|
$cname = $child->name();
|
||
|
if (is_null($cname))
|
||
|
{
|
||
|
_MiniXMLLog("MiniXMLElement::_validateChild() children must be named");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Check for loops */
|
||
|
if ($child == $this)
|
||
|
{
|
||
|
_MiniXMLLog("MiniXMLElement::_validateChild() Trying to append self as own child!");
|
||
|
return 0;
|
||
|
} elseif ( $this->xavoidLoops && $child->parent())
|
||
|
{
|
||
|
_MiniXMLLog("MiniXMLElement::_validateChild() Trying to append a child ($cname) that already has a parent set "
|
||
|
. "while avoidLoops is on - aborting");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
/* createChild ELEMENTNAME [VALUE]
|
||
|
**
|
||
|
** Creates a new MiniXMLElement instance and appends it to the list
|
||
|
** of this element's children.
|
||
|
** The new child element's name is set to ELEMENTNAME.
|
||
|
**
|
||
|
** 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 new child element
|
||
|
**
|
||
|
** Note: don't forget to use the =& (reference assignment) operator
|
||
|
** when calling createChild:
|
||
|
**
|
||
|
** $newChild =& $myElement->createChild('newChildName');
|
||
|
**
|
||
|
*/
|
||
|
function & createChild ($name, $value=NULL)
|
||
|
{
|
||
|
if (! $name)
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::createChild() Must pass a NAME to createChild.");
|
||
|
}
|
||
|
|
||
|
if (! is_string($name))
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::createChild() Name of child must be a STRING");
|
||
|
}
|
||
|
|
||
|
$child = new MiniXMLElement($name);
|
||
|
|
||
|
$appendedChild =& $this->appendChild($child);
|
||
|
|
||
|
if (! $appendedChild )
|
||
|
{
|
||
|
_MiniXMLLog("MiniXMLElement::createChild() '$name' child NOT appended.");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (! is_null($value))
|
||
|
{
|
||
|
if (is_numeric($value))
|
||
|
{
|
||
|
$appendedChild->numeric($value);
|
||
|
} elseif (is_string($value))
|
||
|
{
|
||
|
$appendedChild->text($value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$appendedChild->avoidLoops($this->xavoidLoops);
|
||
|
|
||
|
return $appendedChild;
|
||
|
|
||
|
} /* end method createChild */
|
||
|
|
||
|
|
||
|
|
||
|
/* removeChild CHILD
|
||
|
** Removes CHILD from this element's list of children.
|
||
|
**
|
||
|
** Returns the removed child, if found, NULL otherwise.
|
||
|
*/
|
||
|
|
||
|
function &removeChild (&$child)
|
||
|
{
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("Element::removeChild() called for element without any children.") ;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
$foundChild = NULL;
|
||
|
$idx = 0;
|
||
|
while ($idx < $this->xnumChildren && ! $foundChild)
|
||
|
{
|
||
|
if ($this->xchildren[$idx] == $child)
|
||
|
{
|
||
|
$foundChild =& $this->xchildren[$idx];
|
||
|
} else {
|
||
|
$idx++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (! $foundChild)
|
||
|
{
|
||
|
if (MINIXML_DEBUG > 0)
|
||
|
{
|
||
|
_MiniXMLLog("Element::removeChild() No matching child found.") ;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
array_splice($this->xchildren, $idx, 1);
|
||
|
|
||
|
$this->xnumChildren--;
|
||
|
if ($this->isElement($foundChild))
|
||
|
{
|
||
|
$this->xnumElementChildren--;
|
||
|
}
|
||
|
|
||
|
unset ($foundChild->xparent) ;
|
||
|
return $foundChild;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* removeAllChildren
|
||
|
** Removes all children of this element.
|
||
|
**
|
||
|
** Returns an array of the removed children (which may be empty)
|
||
|
*/
|
||
|
function &removeAllChildren ()
|
||
|
{
|
||
|
$emptyArray = array();
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
return $emptyArray;
|
||
|
}
|
||
|
|
||
|
$retList =& $this->xchildren;
|
||
|
|
||
|
$idx = 0;
|
||
|
while ($idx < $this->xnumChildren)
|
||
|
{
|
||
|
unset ($retList[$idx++]->xparent);
|
||
|
}
|
||
|
|
||
|
$this->xchildren = array();
|
||
|
$this->xnumElementChildren = 0;
|
||
|
$this->xnumChildren = 0;
|
||
|
|
||
|
|
||
|
return $retList;
|
||
|
}
|
||
|
|
||
|
|
||
|
function & remove ()
|
||
|
{
|
||
|
$parent =& $this->parent();
|
||
|
|
||
|
if (!$parent)
|
||
|
{
|
||
|
_MiniXMLLog("XML::Mini::Element::remove() called for element with no parent set. Aborting.");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
$removed =& $parent->removeChild($this);
|
||
|
|
||
|
return $removed;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* parent NEWPARENT
|
||
|
**
|
||
|
** The parent() method is used to get/set the element's parent.
|
||
|
**
|
||
|
** If the NEWPARENT parameter is passed, sets the parent to NEWPARENT
|
||
|
** (NEWPARENT must be an instance of MiniXMLElement)
|
||
|
**
|
||
|
** Returns a reference to the parent MiniXMLElement if set, NULL otherwise.
|
||
|
**
|
||
|
** Note: This method is mainly used internally and you wouldn't normally need
|
||
|
** to use it.
|
||
|
** It get's called on element appends when MINIXML_AUTOSETPARENT or
|
||
|
** MINIXML_AVOIDLOOPS or avoidLoops() > 1
|
||
|
**
|
||
|
*/
|
||
|
function &parent (&$setParent)
|
||
|
{
|
||
|
if (! is_null($setParent))
|
||
|
{
|
||
|
/* Parents can only be MiniXMLElement objects */
|
||
|
if (! $this->isElement($setParent))
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::parent(): Must pass an instance of MiniXMLElement to set.");
|
||
|
}
|
||
|
$this->xparent = $setParent;
|
||
|
}
|
||
|
|
||
|
return $this->xparent;
|
||
|
|
||
|
} /* end method parent */
|
||
|
|
||
|
|
||
|
/* avoidLoops SETTO
|
||
|
**
|
||
|
** The avoidLoops() method is used to get or set the avoidLoops flag for this element.
|
||
|
**
|
||
|
** When avoidLoops is true, children with parents already set can NOT be appended to any
|
||
|
** other elements. This is overkill but it is a quick and easy way to avoid infinite loops
|
||
|
** in the heirarchy.
|
||
|
**
|
||
|
** The avoidLoops default behavior is configured with the MINIXML_AVOIDLOOPS define but can be
|
||
|
** set on individual elements (and automagically all the element's children) with the
|
||
|
** avoidLoops() method.
|
||
|
**
|
||
|
** Returns the current value of the avoidLoops flag for the element.
|
||
|
**
|
||
|
*/
|
||
|
function avoidLoops ($setTo = NULL)
|
||
|
{
|
||
|
if (! is_null($setTo))
|
||
|
{
|
||
|
$this->xavoidLoops = $setTo;
|
||
|
}
|
||
|
|
||
|
return $this->xavoidLoops;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* toString [SPACEOFFSET]
|
||
|
**
|
||
|
** toString returns an XML string based on the element's attributes,
|
||
|
** and content (recursively doing the same for all children)
|
||
|
**
|
||
|
** The optional SPACEOFFSET parameter sets the number of spaces to use
|
||
|
** after newlines for elements at this level (adding 1 space per level in
|
||
|
** depth). SPACEOFFSET defaults to 0.
|
||
|
**
|
||
|
** If SPACEOFFSET is passed as MINIXML_NOWHITESPACES.
|
||
|
** 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 the XML string.
|
||
|
**
|
||
|
**
|
||
|
** Note: Since the toString() method recurses into child elements and because
|
||
|
** of the MINIXML_NOWHITESPACES and our desire to avoid testing for this value
|
||
|
** on every element (as it does not change), here we split up the toString method
|
||
|
** into 2 subs: toStringWithWhiteSpaces(DEPTH) and toStringNoWhiteSpaces().
|
||
|
**
|
||
|
** Each of these methods, which are to be considered private (?), in turn recurses
|
||
|
** calling the appropriate With/No WhiteSpaces toString on it's children - thereby
|
||
|
** avoiding the test on SPACEOFFSET
|
||
|
*/
|
||
|
|
||
|
function toString ($depth=0)
|
||
|
{
|
||
|
if ($depth == MINIXML_NOWHITESPACES)
|
||
|
{
|
||
|
return $this->toStringNoWhiteSpaces();
|
||
|
} else {
|
||
|
return $this->toStringWithWhiteSpaces($depth);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function toStringWithWhiteSpaces ($depth=0)
|
||
|
{
|
||
|
$attribString = '';
|
||
|
$elementName = $this->xname;
|
||
|
$spaces = $this->_spaceStr($depth) ;
|
||
|
|
||
|
$retString = "$spaces<$elementName";
|
||
|
|
||
|
|
||
|
foreach ($this->xattributes as $attrname => $attrvalue)
|
||
|
{
|
||
|
$attribString .= "$attrname=\"$attrvalue\" ";
|
||
|
}
|
||
|
|
||
|
|
||
|
if ($attribString)
|
||
|
{
|
||
|
$attribString = rtrim($attribString);
|
||
|
$retString .= " $attribString";
|
||
|
}
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
/* No kids -> no sub-elements, no text, nothing - consider a <unary/> element */
|
||
|
$retString .= " />\n";
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* If we've gotten this far, the element has
|
||
|
** kids or text - consider a <binary>otherstuff</binary> element
|
||
|
*/
|
||
|
|
||
|
$onlyTxtChild = 0;
|
||
|
if ($this->xnumChildren == 1 && ! $this->xnumElementChildren)
|
||
|
{
|
||
|
$onlyTxtChild = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
if ($onlyTxtChild)
|
||
|
{
|
||
|
$nextDepth = 0;
|
||
|
$retString .= "> ";
|
||
|
} else {
|
||
|
$nextDepth = $depth+1;
|
||
|
$retString .= ">\n";
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
for ($i=0; $i < $this->xnumChildren ; $i++)
|
||
|
{
|
||
|
if (method_exists($this->xchildren[$i], 'toStringWithWhiteSpaces') )
|
||
|
{
|
||
|
|
||
|
$newStr = $this->xchildren[$i]->toStringWithWhiteSpaces($nextDepth);
|
||
|
|
||
|
|
||
|
if (! is_null($newStr))
|
||
|
{
|
||
|
if (! ( preg_match("/\n\$/", $newStr) || $onlyTxtChild) )
|
||
|
{
|
||
|
$newStr .= "\n";
|
||
|
}
|
||
|
|
||
|
$retString .= $newStr;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
_MiniXMLLog("Invalid child found in $elementName ". $this->xchildren[$i]->name() );
|
||
|
|
||
|
} /* end if has a toString method */
|
||
|
|
||
|
} /* end loop over all children */
|
||
|
|
||
|
/* add the indented closing tag */
|
||
|
if ($onlyTxtChild)
|
||
|
{
|
||
|
$retString .= " </$elementName>\n";
|
||
|
} else {
|
||
|
$retString .= "$spaces</$elementName>\n";
|
||
|
}
|
||
|
return $retString;
|
||
|
|
||
|
} /* end method toString */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
function toStringNoWhiteSpaces ()
|
||
|
{
|
||
|
$retString = '';
|
||
|
$attribString = '';
|
||
|
$elementName = $this->xname;
|
||
|
|
||
|
foreach ($this->xattributes as $attrname => $attrvalue)
|
||
|
{
|
||
|
$attribString .= "$attrname=\"$attrvalue\" ";
|
||
|
}
|
||
|
|
||
|
$retString = "<$elementName";
|
||
|
|
||
|
|
||
|
if ($attribString)
|
||
|
{
|
||
|
$attribString = rtrim($attribString);
|
||
|
$retString .= " $attribString";
|
||
|
}
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
/* No kids -> no sub-elements, no text, nothing - consider a <unary/> element */
|
||
|
|
||
|
$retString .= " />";
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* If we've gotten this far, the element has
|
||
|
** kids or text - consider a <binary>otherstuff</binary> element
|
||
|
*/
|
||
|
$retString .= ">";
|
||
|
|
||
|
/* Loop over all kids, getting associated strings */
|
||
|
for ($i=0; $i < $this->xnumChildren ; $i++)
|
||
|
{
|
||
|
if (method_exists($this->xchildren[$i], 'toStringNoWhiteSpaces') )
|
||
|
{
|
||
|
$newStr = $this->xchildren[$i]->toStringNoWhiteSpaces();
|
||
|
|
||
|
if (! is_null($newStr))
|
||
|
{
|
||
|
$retString .= $newStr;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
_MiniXMLLog("Invalid child found in $elementName");
|
||
|
|
||
|
} /* end if has a toString method */
|
||
|
|
||
|
} /* end loop over all children */
|
||
|
|
||
|
/* add the indented closing tag */
|
||
|
$retString .= "</$elementName>";
|
||
|
|
||
|
return $retString;
|
||
|
|
||
|
} /* end method toStringNoWhiteSpaces */
|
||
|
|
||
|
|
||
|
/* toStructure
|
||
|
**
|
||
|
** Converts an element to a structure - either an array or a simple string.
|
||
|
**
|
||
|
** This method is used by MiniXML documents to perform their toArray() magic.
|
||
|
*/
|
||
|
function & toStructure ()
|
||
|
{
|
||
|
|
||
|
$retHash = array();
|
||
|
$contents = "";
|
||
|
$numAdded = 0;
|
||
|
|
||
|
|
||
|
|
||
|
for($i=0; $i< $this->xnumChildren; $i++)
|
||
|
{
|
||
|
if ($this->isElement($this->xchildren[$i]))
|
||
|
{
|
||
|
$name = $this->xchildren[$i]->name();
|
||
|
|
||
|
if (array_key_exists($name, $retHash))
|
||
|
|
||
|
{
|
||
|
if (! (is_array($retHash[$name]) && array_key_exists('_num', $retHash[$name])) )
|
||
|
{
|
||
|
$retHash[$name] = array($retHash[$name],
|
||
|
$this->xchildren[$i]->toStructure());
|
||
|
|
||
|
$retHash[$name]['_num'] = 2;
|
||
|
} else {
|
||
|
array_push($retHash[$name], $this->xchildren[$i]->toStructure() );
|
||
|
|
||
|
$retHash[$name]['_num']++;
|
||
|
}
|
||
|
} else {
|
||
|
$retHash[$name] = $this->xchildren[$i]->toStructure();
|
||
|
}
|
||
|
|
||
|
$numAdded++;
|
||
|
} else {
|
||
|
$contents .= $this->xchildren[$i]->getValue();
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
foreach ($this->xattributes as $attrname => $attrvalue)
|
||
|
{
|
||
|
#array_push($retHash, array($attrname => $attrvalue));
|
||
|
$retHash["_attributes"][$attrname] = $attrvalue;
|
||
|
$numAdded++;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ($numAdded)
|
||
|
{
|
||
|
if (! empty($contents))
|
||
|
{
|
||
|
$retHash['_content'] = $contents;
|
||
|
}
|
||
|
|
||
|
return $retHash;
|
||
|
} else {
|
||
|
return $contents;
|
||
|
}
|
||
|
|
||
|
} // end toStructure() method
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* isElement ELEMENT
|
||
|
** Returns a true value if ELEMENT is an instance of MiniXMLElement,
|
||
|
** false otherwise.
|
||
|
**
|
||
|
** Note: Used internally.
|
||
|
*/
|
||
|
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.
|
||
|
**
|
||
|
** Note: used internally.
|
||
|
*/
|
||
|
function isNode (&$testme)
|
||
|
{
|
||
|
if (is_null($testme))
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return method_exists($testme, 'MiniXMLNode');
|
||
|
}
|
||
|
|
||
|
|
||
|
/* createNode NODEVALUE [ESCAPEENTITIES]
|
||
|
**
|
||
|
** Private (?)
|
||
|
**
|
||
|
** Creates a new MiniXMLNode instance and appends it to the list
|
||
|
** of this element's children.
|
||
|
** The new child node's value is set to NODEVALUE.
|
||
|
**
|
||
|
** Returns a reference to the new child node.
|
||
|
**
|
||
|
** Note: You don't need to use this method normally - it is used
|
||
|
** internally when appending text() and such data.
|
||
|
**
|
||
|
*/
|
||
|
function & createNode (&$value, $escapeEntities=NULL)
|
||
|
{
|
||
|
|
||
|
$newNode = new MiniXMLNode($value, $escapeEntities);
|
||
|
|
||
|
$appendedNode =& $this->appendNode($newNode);
|
||
|
|
||
|
return $appendedNode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* appendNode CHILDNODE
|
||
|
**
|
||
|
** appendNode is used to append an existing MiniXMLNode object to
|
||
|
** this element's list.
|
||
|
**
|
||
|
** Returns a reference to the appended child node.
|
||
|
**
|
||
|
**
|
||
|
** Note: You don't need to use this method normally - it is used
|
||
|
** internally when appending text() and such data.
|
||
|
*/
|
||
|
function &appendNode (&$node)
|
||
|
{
|
||
|
if (is_null($node))
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::appendNode() need to pass a non-NULL MiniXMLNode.");
|
||
|
}
|
||
|
|
||
|
|
||
|
if (! method_exists($node, 'MiniXMLNode'))
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::appendNode() must pass a MiniXMLNode object to appendNode.");
|
||
|
}
|
||
|
|
||
|
if (MINIXML_AUTOSETPARENT)
|
||
|
{
|
||
|
if ($this->xparent == $node)
|
||
|
{
|
||
|
return _MiniXMLError("MiniXMLElement::appendnode() Tryng to append parent $cname as node of "
|
||
|
. $this->xname );
|
||
|
}
|
||
|
$node->parent($this);
|
||
|
}
|
||
|
|
||
|
|
||
|
$idx = $this->xnumChildren++;
|
||
|
$this->xchildren[$idx] = $node;
|
||
|
|
||
|
return $this->xchildren[$idx];
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/* Destructor to keep things clean -- patch by Ilya */
|
||
|
function __destruct()
|
||
|
{
|
||
|
for ($i = 0; $i < count($this->xchildren); ++$i)
|
||
|
$this->xchildren[$i]->xparent = null;
|
||
|
}
|
||
|
|
||
|
|
||
|
} /* end MiniXMLElement class definition */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
****************************************************************************************************
|
||
|
*****
|
||
|
***** MiniXMLElementComment
|
||
|
*****
|
||
|
****************************************************************************************************
|
||
|
***************************************************************************************************/
|
||
|
|
||
|
/* The MiniXMLElementComment class is a specific extension of the MiniXMLElement class.
|
||
|
**
|
||
|
** It is used to create the special <!-- comment --> tags and an instance in created when calling
|
||
|
** $elementObject->comment('this is a comment');
|
||
|
**
|
||
|
** It's methods are the same as for MiniXMLElement - see those for documentation.
|
||
|
**/
|
||
|
|
||
|
class MiniXMLElementComment extends MiniXMLElement {
|
||
|
|
||
|
function MiniXMLElementComment ($name=NULL)
|
||
|
{
|
||
|
$this->MiniXMLElement('!--');
|
||
|
}
|
||
|
|
||
|
|
||
|
function toString ($depth=0)
|
||
|
{
|
||
|
if ($depth == MINIXML_NOWHITESPACES)
|
||
|
{
|
||
|
return $this->toStringNoWhiteSpaces();
|
||
|
} else {
|
||
|
return $this->toStringWithWhiteSpaces($depth);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function toStringWithWhiteSpaces ($depth=0)
|
||
|
{
|
||
|
|
||
|
$spaces = $this->_spaceStr($depth) ;
|
||
|
|
||
|
$retString = "$spaces<!-- \n";
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
/* No kids, no text - consider a <unary/> element */
|
||
|
$retString .= " -->\n";
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
/* If we get here, the element does have children... get their contents */
|
||
|
|
||
|
$nextDepth = $depth+1;
|
||
|
|
||
|
for ($i=0; $i < $this->xnumChildren ; $i++)
|
||
|
{
|
||
|
$retString .= $this->xchildren[$i]->toStringWithWhiteSpaces($nextDepth);
|
||
|
}
|
||
|
|
||
|
$retString .= "\n$spaces -->\n";
|
||
|
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
function toStringNoWhiteSpaces ()
|
||
|
{
|
||
|
$retString = '';
|
||
|
|
||
|
$retString = "<!-- ";
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
/* No kids, no text - consider a <unary/> element */
|
||
|
$retString .= " -->";
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* If we get here, the element does have children... get their contents */
|
||
|
for ($i=0; $i < $this->xnumChildren ; $i++)
|
||
|
{
|
||
|
$retString .= $this->xchildren[$i]->toStringNoWhiteSpaces();
|
||
|
}
|
||
|
|
||
|
$retString .= " -->";
|
||
|
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
****************************************************************************************************
|
||
|
*****
|
||
|
***** MiniXMLElementCData
|
||
|
*****
|
||
|
****************************************************************************************************
|
||
|
***************************************************************************************************/
|
||
|
|
||
|
/* The MiniXMLElementCData class is a specific extension of the MiniXMLElement class.
|
||
|
**
|
||
|
** It is used to create the special <![CDATA [ data ]]> tags and an instance in created when calling
|
||
|
** $elementObject->cdata('data');
|
||
|
**
|
||
|
** It's methods are the same as for MiniXMLElement - see those for documentation.
|
||
|
**/
|
||
|
|
||
|
class MiniXMLElementCData extends MiniXMLElement {
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
function MiniXMLElementCData ($contents)
|
||
|
{
|
||
|
|
||
|
$this->MiniXMLElement('CDATA');
|
||
|
if (! is_null($contents))
|
||
|
{
|
||
|
$this->createNode($contents, 0) ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function toStringNoWhiteSpaces ()
|
||
|
{
|
||
|
return $this->toString(MINIXML_NOWHITESPACES);
|
||
|
}
|
||
|
|
||
|
function toStringWithWhiteSpaces ($depth=0)
|
||
|
{
|
||
|
return $this->toString($depth);
|
||
|
}
|
||
|
|
||
|
function toString ($depth=0)
|
||
|
{
|
||
|
$spaces = '';
|
||
|
if ($depth != MINIXML_NOWHITESPACES)
|
||
|
{
|
||
|
$spaces = $this->_spaceStr($depth);
|
||
|
}
|
||
|
|
||
|
$retString = "$spaces<![CDATA[ ";
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
$retString .= "]]>\n";
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
for ( $i=0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
$retString .= $this->xchildren[$i]->getValue();
|
||
|
|
||
|
}
|
||
|
|
||
|
$retString .= " ]]>\n";
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
****************************************************************************************************
|
||
|
*****
|
||
|
***** MiniXMLElementDocType
|
||
|
*****
|
||
|
****************************************************************************************************
|
||
|
***************************************************************************************************/
|
||
|
|
||
|
/* The MiniXMLElementDocType class is a specific extension of the MiniXMLElement class.
|
||
|
**
|
||
|
** It is used to create the special <!DOCTYPE def [...]> tags and an instance in created when calling
|
||
|
** $elementObject->comment('');
|
||
|
**
|
||
|
** It's methods are the same as for MiniXMLElement - see those for documentation.
|
||
|
**/
|
||
|
|
||
|
class MiniXMLElementDocType extends MiniXMLElement {
|
||
|
|
||
|
var $dtattr;
|
||
|
|
||
|
function MiniXMLElementDocType ($attr)
|
||
|
{
|
||
|
$this->MiniXMLElement('DOCTYPE');
|
||
|
$this->dtattr = $attr;
|
||
|
}
|
||
|
function toString ($depth)
|
||
|
{
|
||
|
if ($depth == MINIXML_NOWHITESPACES)
|
||
|
{
|
||
|
return $this->toStringNoWhiteSpaces();
|
||
|
} else {
|
||
|
return $this->toStringWithWhiteSpaces($depth);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function toStringWithWhiteSpaces ($depth=0)
|
||
|
{
|
||
|
|
||
|
$spaces = $this->_spaceStr($depth);
|
||
|
|
||
|
$retString = "$spaces<!DOCTYPE " . $this->dtattr . " [\n";
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
$retString .= "]>\n";
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
$nextDepth = $depth + 1;
|
||
|
|
||
|
for ( $i=0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
|
||
|
$retString .= $this->xchildren[$i]->toStringWithWhiteSpaces($nextDepth);
|
||
|
|
||
|
}
|
||
|
|
||
|
$retString .= "\n$spaces]>\n";
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
function toStringNoWhiteSpaces ()
|
||
|
{
|
||
|
|
||
|
$retString = "<!DOCTYPE " . $this->dtattr . " [ ";
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
$retString .= "]>\n";
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
for ( $i=0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
|
||
|
$retString .= $this->xchildren[$i]->toStringNoWhiteSpaces();
|
||
|
|
||
|
}
|
||
|
|
||
|
$retString .= " ]>\n";
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
****************************************************************************************************
|
||
|
*****
|
||
|
***** MiniXMLElementEntity
|
||
|
*****
|
||
|
****************************************************************************************************
|
||
|
***************************************************************************************************/
|
||
|
|
||
|
/* The MiniXMLElementEntity class is a specific extension of the MiniXMLElement class.
|
||
|
**
|
||
|
** It is used to create the special <!ENTITY name "val"> tags and an instance in created when calling
|
||
|
** $elementObject->comment('');
|
||
|
**
|
||
|
** It's methods are the same as for MiniXMLElement - see those for documentation.
|
||
|
**/
|
||
|
|
||
|
class MiniXMLElementEntity extends MiniXMLElement {
|
||
|
|
||
|
|
||
|
|
||
|
function MiniXMLElementEntity ($name, $value=NULL)
|
||
|
{
|
||
|
|
||
|
$this->MiniXMLElement($name);
|
||
|
|
||
|
if (! is_null ($value))
|
||
|
{
|
||
|
$this->createNode($value, 0);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function toString ($depth = 0)
|
||
|
{
|
||
|
|
||
|
$spaces = '';
|
||
|
if ($depth != MINIXML_NOWHITESPACES)
|
||
|
{
|
||
|
$spaces = $this->_spaceStr($depth);
|
||
|
}
|
||
|
|
||
|
$retString = "$spaces<!ENTITY " . $this->name();
|
||
|
|
||
|
if (! $this->xnumChildren)
|
||
|
{
|
||
|
$retString .= ">\n";
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
$nextDepth = ($depth == MINIXML_NOWHITESPACES) ? MINIXML_NOWHITESPACES
|
||
|
: $depth + 1;
|
||
|
$retString .= '"';
|
||
|
for ( $i=0; $i < $this->xnumChildren; $i++)
|
||
|
{
|
||
|
|
||
|
$retString .= $this->xchildren[$i]->toString(MINIXML_NOWHITESPACES);
|
||
|
|
||
|
}
|
||
|
$retString .= '"';
|
||
|
$retString .= " >\n";
|
||
|
|
||
|
return $retString;
|
||
|
}
|
||
|
|
||
|
|
||
|
function toStringNoWhiteSpaces ()
|
||
|
{
|
||
|
return $this->toString(MINIXML_NOWHITESPACES);
|
||
|
}
|
||
|
|
||
|
function toStringWithWhiteSpaces ($depth=0)
|
||
|
{
|
||
|
return $this->toString($depth);
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
?>
|