|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2002-06-10 11:44 UTC] mfischer@php.net
[2002-06-10 12:18 UTC] duncan at emarketeers dot com
[2002-06-10 15:12 UTC] sniper@php.net
[2002-09-11 11:16 UTC] sniper@php.net
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 00:00:02 2025 UTC |
Under some circumstances PHP seems to lose track of the number of references it has to a variable (at least, that is what I think is happening). In the following script, look for the line "/** remove the following line and things break **/" in TelesInvoiceParser::_endElement(). The critical lines are: $this->currentElement =& $this->currentElement->parent; which fails, and: $p =& $this->currentElement->parent; $this->currentElement =& $this->currentElement->parent; which works. It appears that the dummy reference $p is needed for the parent property to continue to exist out of the scope of the method. ======== Explanation of script ================ What is happening is that as an XML document is parsed, every time a new element is found a matching object is created and set to be the new "currentElement" and this new currentElement's "parent" property is set to a reference to the previous currentElement. In this way when the element is closed we can get back to its enclosing element. ============= PHP configure flags ============== ./configure --with-apache=../apache_1.3.19/ --with-mysql --with-xslt-sablot --enable-xslt --with-expat-dir=/usr The input XML is ======== XML =========== <invoice> <from> <date day="15" month="12" year="2001"/> </from> <to> <date day="14" month="12" year="2001"/> </to> <issuer>1</issuer> <person id="1234"> <order>4567</order> <traffic no="0" rate="0" zone="2">24</traffic> <traffic no="1" rate="4" zone="2">48</traffic> <traffic no="2" rate="6" zone="2">96</traffic> <traffic no="3" rate="8" zone="2">37</traffic> </person> </invoice> ========== END XML ============== ========== PHP =================== <? //// // Class to parse a Xc Invoice XML Document //// class XcXMLElement { var $parent = null; var $cdata = ""; function setA($attributes) { global $indent; $indent.=" "; echo "<p>$indent Setting up a new ".get_class($this)."</p>\n"; foreach($attributes as $name => $value) { $this->$name = $value; } } function setD($cdata) { $this->cdata .= $cdata; } function end() { global $indent; echo "<p>$indent end of element ".get_class($this)."</p>\n"; $indent = substr($indent,0,strlen($indent) - 14); } } class XcInvoice extends XcXMLElement { var $from, $to, $issuer, $person=array(); function end() { $this->parent->invoice =& $this; parent::end(); } } class XcFrom extends XcXMLElement { var $date; function end() { $this->parent->from =& $this; parent::end(); } } class XcTo extends XcXMLElement { var $date; function end() { $this->parent->to =& $this; parent::end(); } } class XcDate extends XcXMLElement { var $day, $month, $year; function timestamp() { return $this->year.$this->leading($this->month,2).$this->leading($this->day,2)."000000"; } function leading($value,$length) { //// // Make sure there are the right number of leading zeros on a number //// $num = "0000$value"; return substr($value,-$length); } function end() { $this->parent->date =& $this; parent::end(); } } class XcPerson extends XcXMLElement { var $id; var $order; var $traffic = array(); function end() { //// // When a complete person object has been read, we write its data to the database //// global $indent; echo "$indent Writing a person to the database<br>"; echo "$indent Data for the period ".$this->parent->from->date->timestamp()." to ".$this->parent->to->date->timestamp()."<br>\n"; parent::end(); } } class XcOrder extends XcXMLElement { } class XcIssuer extends XcXMLElement { } class XcTraffic extends XcXMLElement { var $no, $rate, $zone; var $class="XcTraffic"; } $indent=""; class XcInvoiceParser { var $fp; var $invoice; // Invoice currently being constructed var $fromDate; var $toDate; var $xmlParser; function XcInvoiceParser($filename) { $this->elementHandlers = array( "invoice" => new XcInvoice, "from" => new XcFrom, "to" => new XcTo, "date" => new XcDate, "issuer" => new XcIssuer, "person" => new XcPerson, "order" => new XcOrder, "traffic" => new XcTraffic ); $this->fp = fopen($filename,"r"); $this->state = null; $this->invoice = null; $this->fromDate = null; $this->toDate = null; $this->issuer = null; $this->xmlParser = xml_parser_create(); xml_set_object($this->xmlParser, &$this); xml_set_element_handler($this->xmlParser,"startElement","endElement"); xml_set_character_data_handler($this->xmlParser, "cdata"); xml_parser_set_option($this->xmlParser,XML_OPTION_CASE_FOLDING,false); $this->level = 0; } function startElement($parser,$element,$attributes) { $this->level++; echo "start element $element at level $this->level <br>\n"; flush(); if($handler = $this->elementHandlers[$element]) { $handler->parent =& $this->currentElement; $this->currentElement =& $handler; $this->currentElement->setA($attributes); } else { echo "Unknown element $element"; exit; } } function endElement($parser,$element) { $this->_endElement($parser, $element); echo "Ended OK"; flush(); } function _endElement($parser,$element) { echo "ending element $element at level $this->level .."; flush(); $this->currentElement->end(); $this->level--; if(!$this->currentElement->parent) { echo "Oops!! "; exit; } echo "popping up the stack from ".get_class($this->currentElement)." to ".get_class($this->currentElement->parent)."..<br>\n"; flush(); /** remove the following line and things break!! **/ $p =& $this->currentElement->parent; $this->currentElement =& $this->currentElement->parent; echo "popped<br>\n"; flush(); echo "currentElement is now ".get_class($this->currentElement)."<br>\n"; flush(); } function cdata($parser,$cdata) { if(!$this->currentElement) { echo "Can't set CDATA on a null element<br>\n"; flush(); exit; } $this->currentElement->setD($cdata); } function parse() { while($line = fread($this->fp,4096)) { if(!xml_parse($this->xmlParser, $line, feof($this->fp))) { echo "ERROR READING FILE"; exit; } } } } $p = new XcInvoiceParser("/tmp/toto"); $p->parse(); ?> ===================== END PHP ========================