Search code examples
phpxmlreader

xml reader opens the file but still gives the 'Load Data before trying to read' error


I have this weird error I don't really know how is this possible. The xmlreader reads the file, but when i am trying to iterate it, it still gives me the error "Message: XMLReader::read(): Load Data before trying to read".

Here is my code:

$what = 'title';
    $reader = new XMLReader;

    if (!$reader->open(base_url().'resources/thexml.xml'))
    {
        die("Failed to open");
    }
    else 
    {
        echo 'success!';
    }


    while($reader->read())
    {
        if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'item')
        {
            $exp = $reader->expand();
            if ($exp->nodeName == $what)
                echo "<b>" . $exp->nodeName . " : </b>" . $exp->nodeValue . "<br />";

        }

        $reader->close();
    }

And this is the output:

success! A PHP Error was encountered

Severity: Warning

Message: XMLReader::read(): Load Data before trying to read

Filename: controllers/welcome.php

Line Number: 102

The success shows it reads the file but still gives me the error that I need to open first. Line number 102 is "while($reader->read())" line. Please help


Solution

  • I found out the problem: You need to move the $reader->close(); statement outside of the loop. Otherwise the xml document gets closed after the first loop and the subsequent read operations fails.

    The read loop should look like this:

    while($reader->read())
    {
        if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'item')
        {
            $exp = $reader->expand();
            if ($exp->nodeName == $what)
                echo "<b>" . $exp->nodeName . " : </b>" . $exp->nodeValue . "<br />";
    
        }
    }
    
    // Close the document after(!) the loop
    $reader->close();
    

    Having this your code works properly.


    However, using XMLReader doesn't seem the appropriate solution here. This because it requires to loop over all(!) tags in the input xml while you are only interested in the <item> nodes. I would use DOMDocument together with XPath here:

    // Create an load the DOM document
    $doc = new DOMDocument();
    $doc->load('thexml.xml');
    
    // Create an XPath selector
    $selector = new DOMXPath($doc);
    
    // Get all <title> nodes inside <item> nodes
    foreach($selector->query('//item/title') as $item) {
        echo '<b>Title: ' . $item->nodeValue . '</br>';
    }