コード例 #1
0
ファイル: Builtin.php プロジェクト: djeraseit/quickbooks-php
 /**
  * XML parsing recursive helper function
  * 
  * @param string $xml
  * @param QuickBooks_XML_Node $root
  * @return void
  */
 protected function _parseHelper($xml, &$Root, &$errnum, &$errmsg, $indent = 0)
 {
     $errnum = QuickBooks_XML::ERROR_OK;
     $errmsg = '';
     $arr = array();
     $xml = trim($xml);
     if (!strlen($xml)) {
         return false;
     }
     $data = '';
     $vstack = array();
     $dstack = array();
     // Remove comments
     while (false !== strpos($xml, '<!--')) {
         $start = strpos($xml, '<!--');
         $end = strpos($xml, '-->', $start);
         if (false !== $start and false !== $end) {
             $xml = substr($xml, 0, $start) . substr($xml, $end + 3);
         } else {
             break;
         }
     }
     $raw = $xml;
     $current = 0;
     $last = '';
     $i = 0;
     // Parse
     while (false !== strpos($xml, '<')) {
         /*
         print('now examinging:');
         print('--------------');
         print($xml);
         print('-----------');
         print("\n\n\n");
         */
         $opentag_start = strpos($xml, '<');
         $opentag_end = strpos($xml, '>');
         // CDATA check
         if (substr($xml, $opentag_start, 3) == '<![') {
             // Find the end of the CDATA section
             $cdata_end = strpos($xml, ']]>');
             $opentag_start = strpos($xml, '<', $cdata_end + 3);
             $opentag_end = strpos($xml, '>', $cdata_end + 3);
         }
         //print('opentag start/end (' . $opentag_start . ', ' . $opentag_end . ') puts us at: {{' . substr($xml, $opentag_start, $opentag_end - $opentag_start) . '}}' . "\n\n");
         $tag_w_attrs = trim(substr($xml, $opentag_start + 1, $opentag_end - $opentag_start - 1));
         $tag = '';
         $attributes = array();
         $this->_extractAttributes($tag_w_attrs, $tag, $attributes);
         if (substr($tag_w_attrs, 0, 1) == '?') {
             // ignore
         } else {
             if (substr($tag_w_attrs, 0, 1) == '!') {
                 // ignore
             } else {
                 if (substr($tag_w_attrs, -1, 1) == '/') {
                     // ***DO NOT*** completely ignore, auto-closed because it has no children
                     // Completely ignoring causes some SOAP errors for requests like <serverVersion xmlns="http://developer.intuit.com/" />
                     //print('TAG: [' . substr($tag_w_attrs, 0, -1 . ']' . "\n");
                     //print('TWA: [' . $tag . ']' . "\n");
                     //$tag_w_attrs = substr($tag_w_attrs, 0, -1);
                     //$tag = substr($tag, 0, -1);
                     $tag_w_attrs = rtrim($tag_w_attrs, '/');
                     $tag = rtrim($tag, '/');
                     // Shove the item on to the stack
                     array_unshift($vstack, array($tag, $tag_w_attrs, $current + $opentag_end));
                     array_unshift($dstack, array($tag, $tag_w_attrs, $current + $opentag_end));
                     $key = key($vstack);
                     $tmp = array_shift($vstack);
                     $pop = $tag;
                     $gnk = $tag_w_attrs;
                     $pos = $current + $opentag_end;
                     // there is no data, so empty data and the length is 0
                     $length = 0;
                     $data = null;
                     if (count($vstack)) {
                         array_shift($dstack);
                     } else {
                         $dstack[$key] = array($pop, $gnk, $pos, $length, $data);
                     }
                 } else {
                     if (substr($tag_w_attrs, 0, 1) == '/') {
                         // NOTE: If you change the code here, you'll likely have to
                         //	change it in the above else () section as well, as that
                         //	section handles data-less tags like <serverVersion />
                         $tag = substr($tag, 1);
                         $key = key($vstack);
                         $tmp = array_shift($vstack);
                         $pop = $tmp[0];
                         $gnk = $tmp[1];
                         $pos = $tmp[2];
                         if ($pop != $tag) {
                             $errnum = QuickBooks_XML::ERROR_MISMATCH;
                             $errmsg = 'Mismatched tags, found: ' . $tag . ', expected: ' . $pop;
                             return false;
                         }
                         $data = substr($raw, $pos, $current + $opentag_start - $pos);
                         // Handle <![CDATA[ ... ]]> sections
                         if (substr($data, 0, 9) == '<![CDATA[') {
                             $cdata_end = strpos($data, ']]>');
                             // Set the data to the CDATA section...
                             $data = QuickBooks_XML::encode(substr($data, 9, $cdata_end - 9));
                             // ... and remove the CDATA from the remaining XML string
                             //$current = $current + strlen($data) + 12;
                         }
                         if (count($vstack)) {
                             array_shift($dstack);
                         } else {
                             $dstack[$key] = array($pop, $gnk, $pos, $current + $opentag_start - $pos, $data);
                         }
                     } else {
                         array_unshift($vstack, array($tag, $tag_w_attrs, $current + $opentag_end + 1));
                         array_unshift($dstack, array($tag, $tag_w_attrs, $current + $opentag_end + 1));
                     }
                 }
             }
         }
         //print('stacks' . "\n");
         //print_r($vstack);
         //print_r($dstack);
         $xml = substr($xml, $opentag_end + 1);
         $current = $current + $opentag_end + 1;
     }
     if (strlen($xml)) {
         $errnum = QuickBooks_XML::ERROR_GARBAGE;
         $errmsg = 'Found this garbage data at end of stream: ' . $xml;
         return false;
     }
     if (count($vstack)) {
         $errnum = QuickBooks_XML::ERROR_DANGLING;
         $errmsg = 'XML stack still contains this after parsing: ' . var_export($vstack, true);
         return false;
     }
     //print_r($dstack);
     //exit;
     $dstack = array_reverse($dstack);
     $last = '';
     foreach ($dstack as $node) {
         $tag = $node[0];
         $tag_w_attrs = $node[1];
         $start = $node[2];
         if (count($node) < 5) {
             continue;
         }
         $length = $node[3];
         $payload = $node[4];
         $tmp = '';
         $attributes = array();
         $this->_extractAttributes($tag_w_attrs, $tmp, $attributes);
         $Node = new QuickBooks_XML_Node($tag);
         foreach ($attributes as $key => $value) {
             $value = QuickBooks_XML::decode($value, true);
             $Node->addAttribute($key, $value);
         }
         if (false !== strpos($payload, '<')) {
             // The tag contains child tags
             $tmp = $this->_parseHelper($payload, $Node, $errnum, $errmsg, $indent + 1);
             if (!$tmp) {
                 return false;
             }
         } else {
             // This tag has no child tags contained inside it
             // Make sure we decode any entities
             $payload = QuickBooks_XML::decode($payload, true);
             $Node->setData($payload);
         }
         $Root->addChild($Node);
         $last = $tag;
     }
     return $Root;
 }