【问题标题】:PHP: XMLWriter producing illegal namespace declarationPHP:XMLWriter 产生非法命名空间声明
【发布时间】:2017-06-19 01:30:06
【问题描述】:

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 发生冲突

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

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

编辑:以防万一,我使用的是 PHP 5.4.16 和 libxml2 2.7.8。

【问题讨论】:

    标签: php xml xmlwriter


    【解决方案1】:

    我找到了一种解决方法:要创建命名空间 decl,只需使用:

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

    所以,我认为问题在于 PHP 手册中缺少这方面的文档。

    顺便说一句,我问题中的代码示例是对我实际编写的代码的简化,它使用 XMLReader 和 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
        }
    }
    

    所以,我只是将“属性循环”替换为:

                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 );
                        }
                    }
                }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      相关资源
      最近更新 更多