如何实现一个PHP流 Package 器来修改另一个 Package 器的输出?

sdnqo3pr  于 2023-11-16  发布在  PHP
关注(0)|答案(1)|浏览(102)

我使用PHP zip://流 Package 器逐行解析大型XML文件。例如:

$stream_uri = 'zip://' . __DIR__ . '/archive.zip#foo.xml';
$reader     = new XMLReader();
$reader->open( $stream_uri, null );
$reader->read();

while ( true ) {
    echo( $reader->readInnerXml() . PHP_EOL );
    if ( ! $reader->next() ) {
        break;
    }
}

字符串
XML文件经常会包含XMLReader不喜欢的可疑UTF控制字符,所以我想实现一个自定义的流 Package 器,我可以将zip://流的输出传递给它,它将在每行运行preg_replace来删除这些字符。
我的梦想是能够做到这一点:

stream_wrapper_register( 'xmlchars', 'XML_Chars' );
$stream_uri = 'xmlchars://zip://' . __DIR__ . '/archive.zip#foo.xml';


然后让XMLReader愉快地读取整理好的节点。我已经找到了一种方法来根据传递给我的 Package 器的路径重构zip流URI:

class XML_Chars {

    protected $stream_uri = '';
    protected $handle;

    function stream_open( $path, $mode, $options, &$opened_path ) {
        $parsed_url     = parse_url( $path );
        $this->stream_uri = 'zip:' . $parsed_url['path'] . '#' . $parsed_url['fragment'];

        return true;
    }

}


但是我对打开zip://流的最佳方法感到困惑,这样我就可以修改它的输出并将结果传递给XMLReader。有人给予关于如何实现这一点的建议吗?

eh57zj3b

eh57zj3b1#

为了对其他人有用,我找到了一种不同的方法来解决这个问题:流过滤器。你可以这样定义它:

class UTF_Character_Filter extends php_user_filter {
    public function filter( $in, $out, &$consumed, $closing ) {
        while ( $bucket = stream_bucket_make_writeable( $in ) ) {
            $consumed += $bucket->datalen;
            // Remove characters in the hex range 0 - 8, B and C, E to 1F
            // i.e. all control characters except newline, tab and return
            $bucket->data = preg_replace( '|[\x0-\x8\xB-\xC\xE-\x1F]|ms', '', $bucket->data );
            stream_bucket_append( $out, $bucket );
        }

        return PSFS_PASS_ON;
    }
}

stream_filter_register( 'utf_character_filter', 'UTF_Character_Filter' );

字符串
像这样使用它:

php://filter/read=utf_character_filter/resource=zip://archive.zip#import.xml


我仍然很想知道是否有人想出了如何制作一个可以接受另一个流 Package 器输入的流 Package 器,因为它可能是一个方便的工具。

相关问题