prewk/xml-string-streamer

Feature Question..

Closed this issue · 3 comments

I am wondering if it is possible (since this is a streamer) to somehow make a call to count the elements that will be processed from the file? I am writing a CLI application and in order to implement a progress meter I would need to know how many total items will be processed to track processed vs remaining.

Yeah, counting the progress as-you-go is of course easy, you just do this:

$counter = 0;
while ($node = $streamer->getNode()) {
    $counter++;
}

Knowing in advance how many elements there are, before parsing through them, is another thing however. If you're in *nix you could do something like:

$totalCount = intval(trim(exec("grep -o '<YourElement>' path/to/file.xml | wc -l")));
$this->progressBarThing->setTotalCount($totalCount);

$progress = 0;
while ($node = $streamer->getNode()) {
    $this->progressBarThing->reportProgress($progress);
}

..if you have some kind of progressBarThing class you want to use.

A much better way for progress is to use size of file vs bytes parsed instead with an (unfortunately undocumented) callback to the stream class. A simple example:

use Prewk\XmlStringStreamer;
use Prewk\XmlStringStreamer\Stream\File;
use Prewk\XmlStringStreamer\Parser\StringWalker;

class Foo
{
    // ....

    private $someProgressBarClass;

    public function parse()
    {
        $file = "path/to/file.xml";
        // Total = XML file size
        $this->someProgressBarClass->setTotalCount(filesize($file));

        $stream = new File($file, 16384, function($chunk, $readBytes) {
            // This closure will be called every time the streamer requests a new chunk of data from the XML file
            $this->someProgressBarClass->reportProgress($readBytes);
        });
        $parser = new StringWalker;

        $streamer = new XmlStringStreamer($parser, $stream);
        while ($node = $streamer->getNode()) {
            // ....
        }
    }
}

I have used this technique myself for CLI progress bars.

Let me know if you need a clearer example :)

Man that's awesome thank you very much for the example on how to get the count before parsing. I am on a *nix (mac) so that will work for me. Thank you again!

NP :) Glad I could help!