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

如何实现PHP流包装器来修改另一个包装器的输出?,php,xml,stream,xmlreader,php-stream-wrappers,Php,Xml,Stream,Xmlreader,Php Stream Wrappers,我使用PHPzip://流包装器逐行解析大型XML文件。例如: $stream\u uri='zip://'__迪鲁/archive.zip#foo.xml'; $reader=newXMLReader(); $reader->open($stream\u uri,null); $reader->read(); while(true){ echo($reader->readInnerXml().PHP\u EOL); 如果(!$reader->next()){ 打破 } } XML文件通常会包

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

$stream\u uri='zip://'__迪鲁/archive.zip#foo.xml';
$reader=newXMLReader();
$reader->open($stream\u uri,null);
$reader->read();
while(true){
echo($reader->readInnerXml().PHP\u EOL);
如果(!$reader->next()){
打破
}
}
XML文件通常会包含不可靠的UTF控制字符
XMLReader
不喜欢。因此,我想实现一个自定义流包装器,我可以将
zip://
流的输出传递给它,它将在每一行上运行
preg\u replace
,以删除这些字符

我的梦想是能够做到这一点:

stream_wrapper_寄存器('xmlchars','xmlchars');
$stream\u uri='1xmlchars://zip://' . __迪鲁/archive.zip#foo.xml';
并让
XMLReader
愉快地阅读整理好的节点。我已经找到了一种基于传递给我的包装器的路径重建zip流URI的方法:

类XML\u字符{
受保护的$stream_uri='';
受保护的$handle;
函数流\u open($path、$mode、$options、&$opened\u path){
$parsed_url=parse_url($path);
$this->stream_uri='zip:'.$parsed_url['path'..\'.$parsed_url['fragment'.];
返回true;
}
}

但是我对打开
zip://
流以便修改其输出并将结果传递给
XMLReader
的最佳方式感到困惑。有谁能给我一些关于如何实现的建议吗?

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

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
然后像这样使用它:

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

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

正在解压XML文件,用以清除特殊字符,然后使用
XMLReader()
一个可行的选项?嗯,XML文件有时可能非常大,所以它们必须在一个流中解压。好的,那么在一个流中解压是一个问题吗?如果可能的话,那应该很好。嗯,我看你已经找到了一种不同的更优雅的方法。我建议您写下并接受自己的答案,以帮助未来的访问者,特别是因为您似乎非常精通PHP。