При необходимости ускорить этот код, который фильтрует данные из XML с помощью класса XmlReader


Я использую XmlReader и избегать помощи SimpleXML, потому что я должен обработать огромный файл и проблемы с памятью, оно не является идеальным решением. Однако, даже я написал ниже скрипт в SimpleXML, это дает мне результат действительно гораздо быстрее.

Потому что скорость и памяти должны для этого проекта, есть ли способ, чтобы ускорить этот код? Что он делает, он фильтрует книг и показать тем, что содержит слово на jQuery.

error_reporting(~0);

$xml = <<<EOD
<?xml version="1.0" encoding="ISO-8859-1"?>
<library>
    <book isbn="781">
        <name>SCJP 1.5</name>
        <info>Sun Certified Java Programmer book</info>
    </book>
    <book isbn="194">
        <name>jQuery is Awesome!</name>
        <info>jQuery Reference Book</info>
    </book> 
    <book isbn="199">
        <name>jQuery 101</name>
        <info>All you need to know about jQuery</info>
    </book> 
</library>
EOD;

$file = 'data://text/plain;base64,'.base64_encode($xml);

class XMLBookIterator implements iterator
{
    private $file;
    private $reader;
    private $state;
    private $key = 0;
    private $book;
    private $valid;
    public function __construct($file)
    {
        $this->file = $file;
    }
    public function current()
    {
        return $this->book;
    }
    public function key()
    {
        return $this->key;
    }
    public function next()
    {
        $reader = $this->reader;
        while ($next = $reader->read())
        {
            switch ($reader->nodeType)
            {
                case (XMLREADER::ELEMENT):
                    $case = $reader->localName.'|'.$this->state;
                    switch($case)
                    {
                        case 'library|0':
                            break;
                        case 'book|1':
                            $this->book = new stdClass;
                            $this->book->isbn = $reader->getAttribute('isbn');                
                            break;
                        case 'name|2':
                            $this->book->name = $reader->readInnerXML();
                            break;
                        case 'info|3':
                            $this->book->info = $reader->readInnerXML();
                            $this->state=0;
                            break;
                        default:
                            throw new Exception(sprintf('Invalid State: %s.', $case));
                    }
                    $this->state++;
                    if ($this->state === 1) break 2;
            }
        }
        $this->valid = $next;
        $this->key++;
    }
    public function rewind()
    {
        if ($this->reader) $this->reader->close();
        $this->reader = new XMLReader();
        $this->reader->open($this->file);
        $this->state = 0;
        $this->next(); // move to first element or invalidate
        if ($this->valid) $this->next(); // get first book
        $this->key = 0;
    }
    public function valid()
    {
        return $this->valid;
    }
}

class BookFilterIterator extends FilterIterator
{
    private $term;
    public function __construct($iterator, $term)
    {
        parent::__construct($iterator);
        $this->term = $term;
    }
    public function accept() {
        $book = parent::current();
        $name = $book->name;
        return false !== stripos($name, $this->term);
    }
}

// filtered books:

$books = new XMLBookIterator($file);

$filtered = new BookFilterIterator($books, 'jQuery');

foreach($filtered as $key => $book)
{
    echo 'book (', $key, '):', "\n";
    print_r($book);
}


434
3
задан 21 июля 2011 в 07:07 Источник Поделиться
Комментарии
1 ответ

Ваш код выглядит довольно аккуратно и легко понять, поздравления. Но может быть, вы можете проверить, для встроенной функции. XPath может поиск предметов для вас:

http://www.php.net/manual/en/simplexmlelement.xpath.php
http://www.w3schools.com/xpath/xpath_syntax.asp

2
ответ дан 24 июля 2011 в 07:07 Источник Поделиться