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, ) ** ** 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 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 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 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 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 *** *** *** *** Can't get here from tag or from the first 'nested' *** *** *** 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: ** ** ** ** ** ** ** ** DA42 ** ** ** D99983FFF ** ** ** ss-839uent ** ** ** ** ** $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 element */ $retString .= " />\n"; return $retString; } /* If we've gotten this far, the element has ** kids or text - consider a otherstuff 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 .= " \n"; } else { $retString .= "$spaces\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 element */ $retString .= " />"; return $retString; } /* If we've gotten this far, the element has ** kids or text - consider a otherstuff 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 .= ""; 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 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"; 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 = ""; 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 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 = "$spacesxnumChildren) { $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 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 = "$spacesdtattr . " [\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 = "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 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 = "$spacesname(); 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); } } ?>