0

PHP DomDocument クラスでサイトマップを作成したい。Kohana モデルを使用してデータベースからデータを取得しようとすると、次の内容のエラーが表示されます。

ドキュメントの先頭にない XML 宣言

モデル アクセスでこれらの 2 行を削除すると、すべて正常に動作しますが、何が問題なのですか? URL を作成するには、このデータが必要です。

私はこの機能を使用しています:

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 要素が追加されます。

そして、出力があります。よく読んでみると、コードを改善するためのちょっとしたヒントがすでにいくつか見つかります。とにかく、これまでの出力例は次のとおりです。

<?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 ドキュメントの前ではなく、XML ドキュメントの内部にあります。エラーはなくなりました。

自分で試してみてください (または、トラブルシューティングを開始して、モデルが Stdout ではなく Stdout に出力される理由を見つけてください。


特別な注意:要素ノードをドキュメントに追加し、後でドキュメント内のそのノードに子を追加する場合は、変数を再割り当てする必要があります。

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

それ以外の場合$r、要素はドキュメントに追加されません。したがって、後でもう一度追加する必要がありますが、これはあなたが望むものではありません。詳細DOMDocument::appendChild()な説明とその例を示すコード例については、 を参照してください。

于 2013-03-11T23:34:46.723 に答える