php - 使用 SAX 和 XPATH 解析大型 XML 文件

标签 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 可以做到这一点,但我不知道如何使用它。 感谢您抽出时间。

最佳答案

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

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

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

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

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

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

    函数 endElement($xml_parser, $name)

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

    函数characterData($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);

关于php - 使用 SAX 和 XPATH 解析大型 XML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27542104/

相关文章:

php - 如何在codeigniter中减去时间和日期?

java - 使用 Logback-test.xml 将时间戳添加到日志文件

PHP:字符串索引

PHP 将字符串转换为十六进制和将十六进制转换为字符串

java - Android通过http读取xml

c# - 使用 LINQ 编辑 XML 输出

parsing - 创建类型为 Parser a -> Parser b -> Parser (要么 a b)的解析器组合器

c++ - C程序解决其中包含函数的表达式

algorithm - 有限语言的克莱恩之星什么时候免费?

php - 最高效的 MySQL 查询?