【问题标题】:XMLReader errorXMLReader 错误
【发布时间】:2014-03-20 01:32:37
【问题描述】:

我必须为我的商店解析 3 个远程 XML 文件(产品、价格、类别),其中最大的文件约为 500MB+。我必须解析它们并插入到 mysql 数据库中。

我可以从 2 种格式中选择

  1. 所有 3 个 XML 文件都压缩在一个 .tar.gz 存档中
  2. 每一个单独,简单的.xml

所以,基本上我有两个选择(我认为)

  1. 在流​​式传输时“随时随地”解析 XML
  2. 下载压缩的 XML 然后解析它

我对这两个都有问题。

  1. 在流式传输时“随时随地”解析 XML

        $url = "http://example.xml";
        $reader = new XMLReader();
        $reader->open($url);
        $item = array();
        while ($reader->read()) {
           switch ($reader->nodeType) {
              case (XMLReader::ELEMENT):
                 if ($reader->localName == 'item') {
                    $item = array();
                    $item['id'] = $reader->getAttribute('id');
                    while ($reader->read()){
                       if ($reader->nodeType == XMLReader::ELEMENT) {
                          $name = strtolower($reader->localName);
                          $reader->read();
                          $item[$name] = $reader->value;
                       }
                       if ($reader->nodeType == XMLReader::END_ELEMENT && $reader->localName == 'item')
                          break;
                    }
                    // Yii framework's mysql query
                    Yii::app()->db->createCommand('INSERT INTO `products`              (id, name, parent_id, parent_name, brand, image) VALUES
                    ('.$item['id'].', "'.$item['name'].'", '.$item['parent_id'].', "'.$item['parent_name'].'", "'.$item['brand'].'", "'.$item['img'].'")
                    ')->execute();
    
        }
    

    } }

此代码在 没有 mysql 查询 下工作正常,但如果我输入它们会引发各种错误

解析器错误:文档末尾有额外内容

  1. 下载然后解析

说我想解析myxml.tar.gz里面的products.xml,有可能吗?

    $url = "compress.zlib:///myxml.tar.gz";
    $reader = new XMLReader();
    $reader->open($url);
    $reader->read();

它说文件是空的

【问题讨论】:

  • 如果这是一次性的,请使用 phpMyAdmin 为您导入 XML 文件
  • 我必须大约每 2 小时进行一次。不过谢谢!
  • 通过批量插入 MySQL,您将获得更高的性能。其次,你可以做一个 CRON 作业,它调用一个存储过程在一个位置加载一个 .XML 文件,以便 MySQL Db 每两小时运行一次。
  • @MackieeE 你的回答让我意识到我提出了一个非常愚蠢的问题。你完全正确。谢谢!
  • @user3328597 这根本不是一个愚蠢的问题! =) 即使存储过程和直接导入也有其自身的局限性,除了空格之外,我什至无法想到对Extra Content at end of the document 的体面答案,在导入之前可能需要修剪..

标签: php mysql xml parsing xmlreader


【解决方案1】:

我做的和你一样。

我已经从 Web 服务 zip 存档下载了 3 个 xml 大文件压缩。 我这样做: 在初始化时我设置:

ini_set('max_execution_time', 1000); //600 秒

ini_set('mysql.connect_timeout', 1000); //运行大sql

ini_set('default_socket_timeout', 1000);

我将 zip 文件下载到临时文件夹:

  /**
  * Metoda care scrie arhiva pe hardisc
  * @param $string textul de scris in fisierul zip
  * @return string Calea catre fisiser
  */
 private function write_to_file($string)
{

    $base = $this->tmpPath;
    $date_folder = $base.date('Y_m').DIRECTORY_SEPARATOR.date('d');

    if(!file_exists($date_folder))
    {
        mkdir($date_folder, 0777, TRUE);
    }

    $file = $date_folder.DIRECTORY_SEPARATOR.'products_'.date("Y_m_d_H_i").'.zip';

    // This uses less memory than file_put_contents
    $f = fopen($file, 'w');
    fwrite($f, $string);
    fclose($f);

    return $file;
}

在此之后,我将 xml 文件从 zip 提取到临时文件夹:

    public function dezarhiveaza($file)
{
    $zip = new ZipArchive;
    $res = $zip->open($file);
    if ($res === TRUE) {
      $zip->extractTo($this->tmpPath);
      $zip->close();
        $this->write_log('extract success');
    } else {
        $this->write_log('error ');
    }
}

接下来我从 XML 中提取产品列表,并使用 1000 行进行插入 MySQL 查询:

private function deserializeazaForme()
{
    $formePath=$this->tmpPath.
    "data".DIRECTORY_SEPARATOR.'forme.xml';
    $xml = simplexml_load_file($formePath);         
    $forme = $xml->xpath('//Table');        
    if($forme)
    {           
        $strFormeInsertFirst="INSERT INTO `forme` (`id`, `denumire`) VALUES ";  
        $strFormeInsert=$strFormeInsertFirst;
        foreach ($forme as $key=>$forma) {
            $strFormeInsert .= "(".$forma->id.",'".$forma->denumire."),";   
            if($key%1000==0  && $key >0){
                $strFormeInsert = rtrim($strFormeInsert, ",") ;
                $strFormeInsert .=";";
                $this->runQuery($strFormeInsert);
                $strFormeInsert=$strFormeInsertFirst;
            }
          }
            $strFormeInsert = rtrim($strFormeInsert, ",") ;
            $strFormeInsert .=";";
            $this->runQuery($strFormeInsert);       
    }   
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-26
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多