【问题标题】:Parsing a large XML file with SAX & XPATH使用 SAX 和 XPATH 解析大型 XML 文件
【发布时间】:2014-12-18 08:27:48
【问题描述】:

我有以下代码,它正在解析 xml 文件并根据另一个子值提取子信息。 代码运行良好,但我的 xml 文件超过 200mb,当我尝试解析并获取多个数据时,该网站在大约 4 分钟或更长时间内加载:(

$dom    = new DOMDocument();
$xpath  = new DOMXPath($dom);
$reader = new XMLReader();
$reader->open('http://www.bookingassist.ro/test/HotelsPro.xml');
while ($reader->read()) {
    if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'Hotel') {
        $node = $dom->importNode($reader->expand(), true);
        $dom->appendChild($node);
        $h1name = $xpath->evaluate('string(/Hotel[HotelCode = "'.$hotelCodes[0].'"]/HotelName)', $node);
        $dom->removeChild($node);
        if ($h1name) {
         $reader->close();
         break;
        }
    }
}

如何解析此文档以更快地检索数据。正如我在互联网上搜索的那样,SAX 会做这件事,但我不知道如何使用它。 感谢您的宝贵时间。

【问题讨论】:

  • 该示例不是 SAX,它使用 XMLReader 和 DOM - 不同的 API

标签: php xml parsing sax


【解决方案1】:

DOM 解析器将数据加载到内存中。 SAX 解析器是一个流解析器,我发现它非常快速和高效。

SAX 解析器面临的挑战是您需要知道标签名称并在通过 XML 流式传输时捕获数据。

您需要设置三个函数才能使用 SAX 解析器...

  1. 由 XML 的开始元素(开始标记)触发的第一个函数。此函数返回开始标记的名称和任何属性。

    函数 startElement($xml_parser, $name, $attributes)

  2. 由 XML 的结束元素(结束标记)触发的第二个函数。此函数仅返回结束标记的名称。

    函数 endElement($xml_parser, $name)

  3. 最后,第三个函数处理在开始和结束元素(开始和结束标签)之间流动的字符数据。

    函数字符数据($xml_parser, $data)

您需要将您的逻辑放入这三个函数中以完成工作,即时存储您需要的任何信息。当你遇到不同的开始或结束标签时,使用 CASE 函数做不同的事情。

一旦你有了你的函数,你就可以初始化解析器...... 您必须在 xml_set_element_handlerxml_set_character_data_handler 选项中使用函数名称。

        //Initialise SAX parser
$xml_parser = xml_parser_create("UTF-8"); //With UTF8 encoding

//Set parser options
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true); //This is a default setting of making all tags uppercase, if set to false you will get the tag name as it's set in the XML.
xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, true); //This should skip values with no values
xml_parser_set_option($xml_parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); //Set the output as UTF-8

xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");

现在你可以打开流了....

$xml->open('http://www.bookingassist.ro/test/HotelsPro.xml');

然后你解析数据。 根据是开始标签、结束标签还是字符数据,将触发三个功能之一。

while ($data = read($xml, 4096))
    {
        if (!xml_parse($xml_parser, $data, feof($xml)))     {
            echo "Error in the XML data\t" . xml_error_string(xml_get_error_code($xml_parser)));
            break;
    }

}

一旦解析器完成,释放资源......

xml_parser_free($xml_parser);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-28
    • 2012-06-26
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多