Why is this xmlreader code not working?

后端 未结 3 1134
一个人的身影
一个人的身影 2021-01-07 05:05

I have a file that looks like this:

    
       About.com: Animation Guide         


        
3条回答
  •  孤城傲影
    2021-01-07 05:40

    The reason why it is not working for you is because you only read to the start-tag of the d:Title element and that one got no value:

    if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'd:Title') {
        $title=$xmlReader->value;
    }
    

    You probably wanted to get the nodeValue of that DOM element, but that is not what $xmlReader->value will return. Knowing this there are multiple ways to deal with that:

    1. Expand the node (XMLReader::expand()) and get the nodeValue (quick example):

      $title = $reader->expand()->nodeValue;
      
    2. Process all XMLReader::TEXT (3) and/or XMLReader::CDATA (4) child-nodes your own (decide if a node is a child-node by looking into XMLReader::$depth).

    In any case to streamline your code you can consider to provide what you need directly, for example by creating yourself a set of functions your own or extend the XMLReader class:

    class MyXMLReader extends XMLReader
    {
        public function readToNextElement()
        {
            while (
                $result = $this->read()
                and $this->nodeType !== self::ELEMENT
            ) ;
            return $result;
        }
    
        public function readToNext($localname)
        {
            while (
                $result = $this->readToNextElement()
                and $this->localName !== $localname
            ) ;
            return $result;
        }
    
        public function readToNextChildElement($depth)
        {
            // if the current element is the parent and
            // empty there are no children to go into
            if ($this->depth == $depth && $this->isEmptyElement) {
                return false;
            }
    
            while ($result = $this->read()) {
                if ($this->depth <= $depth) return false;
                if ($this->nodeType === self::ELEMENT) break;
            }
    
            return $result;
        }
    
        public function getNodeValue($default = NULL)
        {
            $node = $this->expand();
            return $node ? $node->nodeValue : $default;
        }
    }
    

    You can then just use this extended class to do your processing:

    $reader = new MyXMLReader();
    $reader->open($uri);
    
    $num = 0;
    while ($reader->readToNext('ExternalPage') and $num < 200) {
        $url = $reader->getAttribute('about');
    
        $depth = $reader->depth;
        $title = $desc = '';
    
        while ($reader->readToNextChildElement($depth)) {
            switch ($reader->localName) {
                case 'Title':
                    $title = $reader->getNodeValue();
                    break;
                case 'Description':
                    $desc = trim($reader->getNodeValue());
                    break;
            }
        }
    
        $num++;
        echo "#", $num, ": ", $url, " - ", $title, " - ", $desc, "
    \n"; }

    As you can see, this has dramatically made your code much more readable. Also you do not need to care each time if you read this all right.

提交回复
热议问题