Page 1 of 1

XML import class problems

Posted: Mon Mar 16, 2009 1:44 am
by hunefalk
Hi,

I'm new to the forum, trying to get some help for a class that another developer has written. I have some experience with programming myself, but not enough with OOP and passing by reference, which is why I have a problem here.

This class is written to import XML from a web service. It should return an array of nodes (Xml objects), but only returns the first 1-2 of 18 elements in the XML doc.

This is what I've discovered so far. The parse() function is where the problem is. The function should return the Xml object ($node) when an element is found. :?

[EDIT] I just tested removing the & in front of $n in the parse() function while loop. It returns all elements, each as a child of the next. [/EDIT]


Running PHP Version 5.2.4-2ubuntu5.5 locally to debug, but I get the same problems with 5.2.5 on my web hosting account.

Code: Select all

 
<?php
class Xml extends Object {
    public $name = '';
    public $attr = array();
    public $elem = array();
    public $text = array();
    public $nodes = array();
    
    public function __get_value() {
        return isset($this->text[0]) ? $this->text[0] : '';
    }
    public function __set_value($val) {
        $this->text[0] = $val;
    }   
    public function locate($type, $id, $value) {
        foreach($this->elem[$type] as $node) {
            if($node->attr[$id] == $value) {
                return $node;
            }
        }
    } 
    public static function read($uri) {
        $xml = new XMLReader();
 
        if(!$xml->open($uri)) {
            drupal_set_message("common.inc (78): Failed to open '$uri' for reading.", "error");
            return false;       
        }
        
        $root = Xml::parse($xml);
        $xml->close();
        return $root;
    }
    public static function parse(&$xml){
        if(!$xml->read()) {
            return false;
        }
        else if($xml->nodeType == XMLReader::END_ELEMENT) {
            return false;
        }
        else if($xml->nodeType == XMLReader::ELEMENT) {         
            $node = new Xml();
            $node->name = $xml->name;
 
            if($xml->hasAttributes) {
                while($xml->moveToNextAttribute()) {
                    $node->attr[$xml->name] = $xml->value;
                }
            }
 
            if(!$xml->isEmptyElement) {
                while($n = Xml::parse($xml)) {
                    if(isset($n->name)) {
                        if($n->name == '#text') {
                            $node->text[] = &$n->value;
                        }
                        else {
                            $node->elem[$n->name][] = &$n;
                        }
                        # Changed from $this->nodes[] = &$n;
                        # since the Xml class is called without being 
                        # instantiated every time.
                        if($this)$this->nodes[] = &$n;
 
                    }
                }
            }
 
            return $node;
        }
        else if($xml->nodeType == XMLReader::TEXT) {
            $node = new stdClass();
            $node->name = $xml->name;
            $node->value = $xml->value;         
            return $node;
        }   
        
        return true;
    } 
};
?>
 
The XML I'm trying to import looks like this:

Code: Select all

<CategorySearch format="List" id="601">
  <Category catalogs="false" id="601" name="Home Page" refinements="false"/>
  <Category catalogs="false" id="100334923" name="Baby & Nursery" refinements="false"/>
  <Category catalogs="false" id="100471423" name="Entertainment" refinements="false"/>
  <Category catalogs="false" id="172601" name="Cars & Accessories" refinements="false"/>
  <Category catalogs="false" id="110001" name="Computers & Software" refinements="false"/>
  <Category catalogs="false" id="120501" name="Electronics" refinements="false"/>
  <Category catalogs="false" id="107301" name="Fashion & Lingerie" refinements="false"/>
  <Category catalogs="false" id="159001" name="Finance" refinements="false"/>
  <Category catalogs="false" id="169901" name="Travel" refinements="false"/>
  <Category catalogs="false" id="117901" name="Games, Consoles & Toys" refinements="false"/>
  <Category catalogs="false" id="100007413" name="Gifts & Gadgets" refinements="false"/>
  <Category catalogs="false" id="132801" name="Health & Beauty" refinements="false"/>
  <Category catalogs="false" id="134301" name="Home & Garden" refinements="false"/>
  <Category catalogs="false" id="144601" name="Household Appliances" refinements="false"/>
  <Category catalogs="false" id="125301" name="Mobiles, Phones & Faxes" refinements="false"/>
  <Category catalogs="false" id="163601" name="Sport & Fitness" refinements="false"/>
  <Category catalogs="false" id="100524123" name="Cashback" refinements="false"/>
</CategorySearch>
However, the only thing returned by the Xml::read() function is the 601 category.

I'm sure there's a simple solution to this, but I am not able to figure it out.

Let me know if I can provide more details for you. Your help is much appreciated! :)