在 PHP 中解析大型 XML 文件

2022-08-30 09:28:45

我正在尝试将DMOZ内容/结构XML文件解析为MySQL,但是所有现有的脚本都非常旧,不能很好地工作。如何在PHP中打开一个大(+ 1GB)XML文件进行解析?


答案 1

只有两个php API真正适合处理大文件。第一个是旧的expat api,第二个是较新的XMLreader函数。这些 api 读取连续流,而不是将整个树加载到内存中(这是 simplexml 和 DOM 所做的)。

例如,您可能希望查看 DMOZ 目录的以下部分解析器:

<?php

class SimpleDMOZParser
{
    protected $_stack = array();
    protected $_file = "";
    protected $_parser = null;

    protected $_currentId = "";
    protected $_current = "";

    public function __construct($file)
    {
        $this->_file = $file;

        $this->_parser = xml_parser_create("UTF-8");
        xml_set_object($this->_parser, $this);
        xml_set_element_handler($this->_parser, "startTag", "endTag");
    }

    public function startTag($parser, $name, $attribs)
    {
        array_push($this->_stack, $this->_current);

        if ($name == "TOPIC" && count($attribs)) {
            $this->_currentId = $attribs["R:ID"];
        }

        if ($name == "LINK" && strpos($this->_currentId, "Top/Home/Consumer_Information/Electronics/") === 0) {
            echo $attribs["R:RESOURCE"] . "\n";
        }

        $this->_current = $name;
    }

    public function endTag($parser, $name)
    {
        $this->_current = array_pop($this->_stack);
    }

    public function parse()
    {
        $fh = fopen($this->_file, "r");
        if (!$fh) {
            die("Epic fail!\n");
        }

        while (!feof($fh)) {
            $data = fread($fh, 4096);
            xml_parse($this->_parser, $data, feof($fh));
        }
    }
}

$parser = new SimpleDMOZParser("content.rdf.u8");
$parser->parse();

答案 2

这是一个与在PHP中处理大型XML的最佳方法非常相似的问题,但是对于DMOZ目录解析的特定问题,有一个非常好的特定答案。但是,由于这对于大型XML来说是一个很好的Google命中,因此我也会从另一个问题中重新发布我的答案:

我对此的看法:

https://github.com/prewk/XmlStreamer

一个简单的类,它将在流式传输文件时将所有子级提取到 XML 根元素。在 pubmed.com 的 108 MB XML 文件上测试。

class SimpleXmlStreamer extends XmlStreamer {
    public function processNode($xmlString, $elementName, $nodeIndex) {
        $xml = simplexml_load_string($xmlString);

        // Do something with your SimpleXML object

        return true;
    }
}

$streamer = new SimpleXmlStreamer("myLargeXmlFile.xml");
$streamer->parse();

推荐