在PHP中处理大型XML文本节点

时间:2016-07-09 18:19:56

标签: php xml

this问题中,讨论了如何使用流解析PHP中的大型XML文档,以便不必将整个文档放在内存中。

但是,XMLReader类似乎不适合解析XML文档中的大型文本节点。由于我使用的API将base64编码的文件作为XML文档的值与一些元数据一起发送,我正在寻找一种流式传输这些文本节点的方法,而不是将值作为字符串返回:

<?php
$reader = XMLReader::open($someStream);

// $reader->read() until a node is reached

// The following puts the whole text node in memory, rather than creating a stream
$content = $reader->value; 
?>

是否可以将$reader->value转换为流?

1 个答案:

答案 0 :(得分:0)

我所提出的是使用PHP的低级XML Parser和一些流功能。

$input = fopen('input.xml', 'r');
$output = fopen('output.txt', 'w');
stream_filter_append($output, 'convert.base64-decode');

将这些传递给创建XML Parser的类:

public function __construct($input, $output) {
    // ...
    $this->xml = xml_parser_create();
    xml_set_object($this->xml, $this);
    xml_set_element_handler($this->xml, 'start', 'end');
    xml_set_character_data_handler($this->xml, 'character');
}

startend方法用于在XML中查找正确的元素,character方法将内容写入输出流:

protected function character($parser, $data)
{
    if ($this->match()) {
        fwrite($this->output, $data);
    }
}

高效的部分是我们称之为解析器的地方,它一次只读取可管理的块:

while ($data = fread($this->input, $bufferSize = 1024)) {
    xml_parse($this->xml, $data, feof($this->input) or $this->done);
}

可以在$this->donestart处理程序中设置end,在我的情况下,我会在找到匹配后立即删除处理程序。

由于这些旧的php函数没有抛出,当然还是必须实现一些安全检查。