2013-03-11 64 views
0

我想用PHP DomDocument类创建站点地图。 当我试图从Kohana的模型数据库获取数据,它显示了一个错误的内容:PHP DomDocument错误 - XML声明不在文档开始处

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; 

} 
+0

你确定这些行不会导致PHP的通知或警告的麻烦? – 2013-03-11 21:51:41

回答

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元素被添加到外面。

然后是输出。如果你仔细阅读,你会发现一些小提示如何改进你的代码。反正这里是迄今为止典型输出:

<?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()了解详细说明和示例代码。