使用SAX&amp ;;解析大型XML文件XPATH

时间:2014-12-18 08:27:48

标签: php xml parsing sax

我有以下代码解析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会做的事情,但我不知道如何使用它。 谢谢你的时间。

1 个答案:

答案 0 :(得分:2)

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

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

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

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

    function startElement($ xml_parser,$ name,$ attributes)

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

    function endElement($ xml_parser,$ name)

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

    function characterData($ xml_parser,$ data)

  4. 您需要将您的逻辑放入这三个功能中来完成工作,即时存储您需要的任何信息。当您使用不同的开始或结束标签时,请使用CASE功能执行不同的操作。

    一旦掌握了功能,就可以初始化解析器...... 您必须使用 xml_set_element_handler 中的函数名称和 xml_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->打开(' http://www.bookingassist.ro/test/HotelsPro.xml&#39);

    你解析数据。 将触发三个功能中的一个,具体取决于它是开始标记,结束标记还是字符数据。

    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);