PHP:XMLWriter生成非法的名称空间声明

时间:2017-06-18 15:50:45

标签: php xml xmlwriter

XMLWriter看起来很破碎,因为它产生的命名空间声明 导致实例格式不正确。

例如:

$writer = new XMLWriter();
$writer->openUri( 'php://output' );

$writer->startIndent( true );
$writer->setIndentString ( "\t" );
$writer->startDocument( '1.0', 'UTF-8' );

$writer->startElement( 'root' );
$writer->writeAttributeNs( 'xmlns', 'bar', 'http://www.w3.org/2000/xmlns/', 'http://example.com' );
$writer->startElementNs( 'bar', 'baz', null );
$writer->endElement();

产生

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:bar="http://example.com" xmlns:xmlns="http://www.w3.org/2000/xmlns/">
    <bar:baz/>
</root>

注意xmlns:xmlns="http://www.w3.org/2000/xmlns/",其中:

  1. 在我写的PHP代码中没有任何内容
  2. Namespace constraint: Reserved Prefixes and Namespace Names
  3. 发生冲突

    无论我做什么,如果我创建任何命名空间声明,那么XMLWriter会输出这个非法的命名空间声明(除了我希望它输出的命名空间声明)。

    我错过了什么?因为,这会使XMLWriter无法使用。

    编辑:如果重要,我使用的是PHP 5.4.16和libxml2 2.7.8。

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方法:创建名称空间decls,只需使用:

$writer->writeAttribute( 'xmlns:prefix', 'http://example.com' );

所以,我认为问题只是缺乏PHP手册中的文档。

BTW,我的问题中的代码示例是我实际编写的代码的简化,它使用XMLReader&amp; amp;来实现对实例的简单转换。 XMLWriter,ala:

$reader = new XMLReader();
$reader->open( $file );

$writer = new XMLWriter();
$writer->openUri( "{$file}-xformed.xml" );
$writer->setIndent( true );
$writer->setIndentString( "\t" );
$writer->startDocument( '1.0', 'UTF-8' );

while ( $reader->read() ) {
    switch ( $reader->nodeType ) {
        case XMLReader::ELEMENT:
            if ( '' === $reader->namespaceURI ) {
                $writer->startElement( $reader->localName );
            }
            else {
                $writer->startElementNS( $reader->prefix, $reader->localName, $reader->namespaceURI );
            }

            if ( $reader->hasAttributes ) {
                while ( $reader->moveToNextAttribute() ) {
                    if ( '' === $reader->namespaceURI ) {
                        $writer->writeAttribute( $reader->name, $reader->value );
                    }
                    else {
                        // this stmt was causing the illegal namespace decls
                        // even tho there is nothing wrong with the code :-(
                        $writer->writeAttributeNS( $reader->prefix, $reader->localName, $reader->namespaceURI, $reader->value );
                    }
                }
            }

            break;

        // other case stmts for other node types
    }
}

所以,我刚刚更换了&#34;属性循环&#34;用:

            if ( $reader->hasAttributes ) {
                while ( $reader->moveToNextAttribute() ) {
                    if ( in_array( $reader->namespaceURI, array( '', 'http://www.w3.org/2000/xmlns/' ) ) {
                        // create an attribute in the empty namespace or a namespace decl
                        $writer->writeAttribute( $reader->name, $reader->value );
                    }
                    else {
                        // create a namespace-qualified attribute
                        $writer->writeAttributeNS( $reader->prefix, $reader->localName, $reader->namespaceURI, $reader->value );
                    }
                }
            }