Вы можете написать streamwrapper, который фильтрует поток.После того, как он найдет первый пробел, он удалит фильтр и начнет передавать данные в XMLWriter.
class ResourceWrapper {
private $_stream;
private $_filter;
private $context;
public static function createContext(
$stream, callable $filter = NULL, string $protocol = 'myproject-resource'
): array {
self::register($protocol);
return [
$protocol.'://context',
\stream_context_create(
[
$protocol => [
'stream' => $stream,
'filter' => $filter
]
]
)
];
}
private static function register($protocol) {
if (!\in_array($protocol, \stream_get_wrappers(), TRUE)) {
\stream_wrapper_register($protocol, __CLASS__);
}
}
public function removeFilter() {
$this->_filter = NULL;
}
public function url_stat(string $path , int $flags): array {
return [];
}
public function stream_open(
string $path, string $mode, int $options, &$opened_path
): bool {
list($protocol, $id) = \explode('://', $path);
$context = \stream_context_get_options($this->context);
if (
isset($context[$protocol]['stream']) &&
\is_resource($context[$protocol]['stream'])
) {
$this->_stream = $context[$protocol]['stream'];
$this->_filter = $context[$protocol]['filter'];
return TRUE;
}
return FALSE;
}
public function stream_read(int $count) {
if (NULL !== $this->_filter) {
$filter = $this->_filter;
return $filter(\fread($this->_stream, $count), $this);
}
return \fread($this->_stream, $count);
}
public function stream_eof(): bool {
return \feof($this->_stream);
}
}
Использование:
$xml = <<<'XML'
<?xml version="1.0"?>
<person><name>Alice</name></person>
XML;
// open the example XML string as a file stream
$resource = fopen('data://text/plain;base64,'.base64_encode($xml), 'rb');
$reader = new \XMLReader();
// create context for the stream and the filter
list($uri, $context) = \ResourceWrapper::createContext(
$resource,
function($data, \ResourceWrapper $wrapper) {
// check for content after removing leading white space
if (ltrim($data) !== '') {
// found content, remove filter
$wrapper->removeFilter();
// return data without leading whitespace
return ltrim($data);
}
return '';
}
);
libxml_set_streams_context($context);
$reader->open($uri);
while ($foundNode = $reader->read()) {
var_dump($reader->localName);
}
Выход:
string(6) "person"
string(4) "name"
string(5) "#text"
string(4) "name"
string(6) "person"