0

我想用 PHP DomDocument 类创建站点地图。当我尝试使用 Kohana 模型从数据库中获取数据时,它显示内容错误:

XML 声明不在文档开头

当我通过模型访问删除这两行时 - 一切正常,有什么问题?我需要这些数据来创建我的网址。

我正在使用这个功能:

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;

}
4

1 回答 1

1

错误

XML 声明不在文档开头

只是意味着您在 XML 声明(即<?xml version="1.0" ... ?>部分)之前有一些输出(数据)。而是将该输出放入文档中。这是一个例子:

<?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');

如您所见,它与您的代码相似。该类的模拟Data_Model只是泄漏了一些数据-因为它可以!是的!并触发一个通知,这就是为什么错误报告被打开并且显示错误被打开的原因(不要在生产中这样做,它在这里是为了示例)。

接下来的内容基本上是您的代码,直到它到达该ob_start()行,然后将ob_get_clean()一个新的 XML 元素添加到 out 中。

然后是输出。如果您仔细阅读,您会发现一些关于如何改进代码的小提示。无论如何,这是迄今为止的示例输出:

<?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>

如您所见,所有输出现在都在 XML 文档中,而不是在它之前。错误消失了。

自己尝试一下(或者开始排除故障,找出为什么你的模型输出到 Stdout 而不是不输出。


额外说明:当您向文档添加元素节点并且稍后想要在文档中向该节点添加子节点时,您需要重新分配变量:

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

否则$r仍然是添加到文档中的元素。所以你需要稍后添加它,这不是你想要的。有关DOMDocument::appendChild()详细说明和示例代码,请参阅。

于 2013-03-11T23:34:46.723 回答