PHP XML解析 - 可以更快吗?

时间:2015-07-29 13:46:08

标签: php xml

我有大型XML文件(400 MB),我需要每天更新它。对于每个主要元素,我使用SELECT + INSERT / UPDATE查询到数据库。当我运行脚本时,它每分钟处理26个主要元素,但它会减慢 - 在500个主要元素之后,它会慢得多(每分钟10个元素)。

    $xml_reader = new XMLReader;
$xml_reader->open("feed.xml");


// move the pointer to the first product
while ($xml_reader->read() && $xml_reader->name != 'SHOPITEM');

// loop through the products
while ($xml_reader->name == 'SHOPITEM')
            {
            // load the current xml element into simplexml and we’re off and running!
            $feed = simplexml_load_string($xml_reader->readOuterXML());

            // now you can use your simpleXML object ($xml).
            //e.g. $feed->PRODUCTNO

            //SELECT, UPDATE/INSERT HERE
    }

    // move the pointer to the next product
    $xml_reader->next('SHOPITEM');
}

// don’t forget to close the file
$xml_reader->close();

这是XML:

<?xml version="1.0" encoding="utf-8"?>
<SHOP>
    <SHOPITEM> 
        <ITEM_ID>2600000394161</ITEM_ID> 
        (+ 15 more elements like this) 
        <PARAM>
            <PARAM_NAME><![CDATA[some data here]]></PARAM_NAME> 
            <VAL><![CDATA[some data here]]></VAL> 
        </PARAM> 
        (+ 10 more elements like this) 
    </SHOPITEM> 
    (lot of shopitems here) 
</SHOP>

由于我的RAM,我无法使用SimpleXML。是否有更快的PHP XML解析器或大型网站的方式(例如价格比较网站)?更好的硬件?当XML处理时,我的CPU占10%,RAM占80%。

3 个答案:

答案 0 :(得分:1)

通过将节点从XMLReader扩展到DOM元素节点,可以加快XML解析,可以将元素节点转换为SimpleXMLElement。

$xml_reader = new XMLReader;
$xml_reader->open("feed.xml");

$dom = new DOMDocument();
$xpath = new DOMXPath($dom);

// move the pointer to the first product
while ($xml_reader->read() && $xml_reader->name != 'SHOPITEM');

// loop through the products
while ($xml_reader->name == 'SHOPITEM') {
  // expand to DOM element
  $element = $xml_reader->expand($dom);

  // use Xpath with the $element as context node
  $itemId = $xpath->evaluate('string(ITEM_ID)', $element);

  // or import it into a SimpleXMLElement
  $item = simplexml_import_dom($element);

  //SELECT, UPDATE/INSERT HERE

  // move the pointer to the next product
  $xml_reader->next('SHOPITEM');
}
// don’t forget to close the file
$xml_reader->close();

为了加快这个过程,您应该收集数据并进行批量插入。大多数DBMS都支持这种方式。较少的SQL查询意味着对数据库的工作量较少,但您需要内存来收集数据。你必须找到一个平衡点。

另一种可能性是生成包含所有SQL语句并使用控制台客户端执行它的本地文件。这可能非常快,但存在潜在的安全风险。

答案 1 :(得分:1)

考虑使用XML数据库(例如eXist或BaseX)。在这种尺寸下,它会更有效率。

答案 2 :(得分:0)

我不能说DOMDocument方法是否比SimpleXML更快,但是使用DOMDocument你会做类似下面的事情(未经测试):

$xmlfile='/path/to/feed.xml';

if( file_exists( $xmlfile ) ){
    libxml_use_internal_errors( TRUE );
    $dom = new DOMDocument('1.0','utf-8');
    $dom->validateOnParse=false;
    $dom->standalone=true;
    $dom->preserveWhiteSpace=true;
    $dom->strictErrorChecking=false;
    $dom->substituteEntities=false;
    $dom->recover=true;
    $dom->formatOutput=false;
    $dom->loadXML( $xmlfile );
    $parse_errs=serialize( libxml_get_last_error() );
    libxml_clear_errors();

    $xpath=new DOMXPath( $dom );

    $items = $dom->getELementsByTagName('SHOPITEM');

    foreach( $items as $node ){

        echo $node->nodeValue;

        /* Each node is likely to have children */
        $children=$xpath->query('PRODUCTNO',$node);
        foreach( $children as $child ){
            echo $child->nodeValue;
        }

        /*
            mysql cmds
            ----------
            select , update, insert
        */
    }

    $dom=null;
}