简体   繁体   English

PHP DomDocument错误-XML声明不在文档的开头

[英]PHP DomDocument error - XML declaration not at the begginning of document

I want to create sitemap with PHP DomDocument class. 我想使用PHP DomDocument类创建站点地图。 When I'm trying to get data from database with Kohana model It shows an error with content: 当我尝试使用Kohana模型从数据库中获取数据时,它显示内容错误:

XML declaration not at beginning of document XML声明不在文档开头

When I delete these two lines with model access - everything works fine, what's wrong? 当我通过模型访问删除这两行时,一切正常,这是怎么回事? I need this data to create my urls. 我需要这些数据来创建我的网址。

I'm using this function: 我正在使用此功能:

public function sitemap()
{
    $doc = new DOMDocument();
    $doc->formatOutput = true;


    $r = $doc->createElementNS("http://www.sitemaps.org/schemas/sitemap/0.9","urlset" );
    $r->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance',
            'xsi:schemaLocation',
            'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd'
            );

    $doc->appendChild( $r );

    $model = new Data_Model; // THESE TWO LINES CAUSES ERROR
    $arrayofdata = $model->get_all();

for($i=0; $i<10; $i++)
{
    $b = $doc->createElement( "url" );
    $loc = $doc->createElement("loc");
    $loc->appendChild($doc->createTextNode('www.example.com'));
    $b->appendChild( $loc );
        $priority = $doc->createElement( "priority" );
        $priority->appendChild(
                    $doc->createTextNode('1.0')
                    );
        $b->appendChild( $priority );


        $r->appendChild( $b );


        $changefreq = $doc->createElement( "changefreq" );
        $changefreq->appendChild(
                    $doc->createTextNode('Daily')
                    );
        $b->appendChild( $changefreq );

        $lastmod = $doc->createElement( "lastmod" );
        $lastmod->appendChild(
                    $doc->createTextNode(date('Y-m-d'))
                    );
    $b->appendChild( $lastmod );

    $r->appendChild( $b );
}
    $output = $doc->saveXML();
    header("Content-type:text/xml");  
    echo $output;

}

the error 错误

XML declaration not at beginning of document XML声明不在文档开头

just means you have got some output (data) before the XML declaration (that is the <?xml version="1.0" ... ?> part). 只是意味着您在XML声明之前有一些输出(数据)(即<?xml version="1.0" ... ?>部分)。 Instead put that output into the document. 而是将输出结果放入文档中。 Here is an example: 这是一个例子:

<?php
error_reporting(~0);
ini_set('display_errors', 1);

class Data_Model {
    public function __construct() {
        echo "I output something just because I can!\n";
    }

    public function get_all() {
        trigger_error('Yes I can trigger notices baby!', E_USER_NOTICE);
        echo "Output, I love it! Just put it out!\n";
        return array();
    }
}

$doc                     = new DOMDocument();
$doc->formatOutput       = TRUE;
$doc->preserveWhiteSpace = FALSE;

$r = $doc->createElementNS("http://www.sitemaps.org/schemas/sitemap/0.9", "urlset");
$r->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance',
    'xsi:schemaLocation',
    'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd'
);
$doc->appendChild($r);

// capture leaked output and create a <buffer> element containing the output (if any) with the
// output XML

ob_start();
$model       = new Data_Model; // THESE TWO LINES CAUSES ERROR
$arrayofdata = $model->get_all();
$buffer      = ob_get_clean();

$bufferElement = $doc->createElement('buffer');
$bufferElement->setAttribute('strlen', strlen($buffer));
$bufferElement->appendChild($doc->createCDATASection($buffer));
$bufferElement = $doc->documentElement->appendChild($bufferElement);

# ... 

// output XML
header("Content-Type: text/xml");
$doc->save('php://stdout');

As you can see it is similar to your code. 如您所见,它与您的代码相似。 The mock of the Data_Model class just leaks some data - because it can! Data_Model类的模拟只会泄漏一些数据-因为可以! Yeah! 是的 And triggers a notice that's why error reporting is switched on high and display errors is on (don't do that in production, it's here for the examples sake). 并触发一条通知,这就是为什么错误报告打开高且显示错误打开的原因(在生产环境中请勿这样做,此处仅出于示例目的)。

What follows is basically your code until it comes to the ob_start() line and then with the ob_get_clean() a new XML element is added to the out. 接下来基本上就是您的代码,直到出现ob_start()行,然后使用ob_get_clean()将新的XML元素添加到输出中。

And then there is the output. 然后有输出。 If you read closely you find already some little hints how to improve your code. 如果仔细阅读,您会发现一些小提示,说明如何改进代码。 Anyway here is the exemplary output so far: 无论如何,这里是到目前为止的示例输出:

<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
  <buffer strlen="640"><![CDATA[I output something just because I can!

Notice: Yes I can trigger notices baby! in \home\user\test-parts.php on line 14

Call Stack:
    0.0006     147024   1. {main}() \home\user\test-parts.php:0
    0.0007     165016   2. Data_Model->get_all() \home\user\test-parts.php:36
    0.0007     165128   3. trigger_error() \home\user\test-parts.php:14

Output, I love it! Just put it out!
]]></buffer>
</urlset>

As you can see, all the output is now inside the XML document and not before it. 如您所见,所有输出现在都在XML文档中,而不是在它之前。 The error is gone. 错误消失了。

Try it out your own (or start troubleshooting finding out why your model outputs to Stdout instead of not. 自己尝试一下(或开始进行故障排除,以找出为什么模型输出到Stdout而不是输出到Stdout的原因。


Extra Note: When you add an element node to the document and you want to add children to that node in the document later on, you need to re-assign the variable: 附加说明:当您向文档中添加元素节点并且以后想要向该节点中的子节点添加子节点时,需要重新分配变量:

$r = $doc->appendChild( $r );
^^^^^

Otherwise $r is still the element not added to the document. 否则$r仍然是添加到文档中的元素。 So you would need to add it later again which is not what you want. 因此,您以后需要再次添加它这不是您想要的。 See DOMDocument::appendChild() for the detailed description and example codes that demonstrate so. 有关详细说明和示例代码,请参见DOMDocument::appendChild()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM