6

PHP で SimpleXML を使用して Google 製品の RSS フィードを作成しています。製品をデータベースから取得し、RSS ファイルを正常に作成していますが、名前空間に関しては問題があります。

私は Google で Stack Overflow を検索して、名前空間を含む XML フィードを解析する方法に関する多数の投稿に出くわしましたが、私の問題は実際には名前空間を含むXML ファイルを作成することです。

ファイル次のようになります。

<?xml version="1.0" encoding="UTF-8" ?>
<rss version ="2.0" xmlns:g="http://base.google.com/ns/1.0">
    <!-- content -->
</rss>

そして、ここに私のコードがあります:

<?php

$xml = new SimpleXMLElement('<rss></rss>');
$xml->addAttribute('version', '2.0');

$xml->addChild('channel');
$xml->channel->addChild('title', 'Removed');
$xml->channel->addChild('description', 'Removed');
$xml->channel->addChild('link', 'Removed');

foreach ($products as $product) {
    $item = $xml->channel->addChild('item');
    $item->addChild('title', htmlspecialchars($product['title']));
    $item->addChild('description', htmlspecialchars($product['title']));
    $item->addChild('link', $product['url']);
    $item->addChild('id', $product['product_id']);
    $item->addChild('price', $product['price_latest']);
    $item->addChild('brand', $product['range']);
    $item->addChild('condition', 'new');
    $item->addChild('image_link', $product['image']);
}

ルート要素の宣言と、各要素の, , ,のプレフィックスとして、g名前空間を導入するにはどうすればよいですか?xmlnsrssidpricebrandconditionimage_linkitem

4

3 に答える 3

12

これは、SimpleXMLElement インターフェイスを使用して実行できます。IMHOこれは最も危険なハックですが、今のところ機能します。

重要な点は、今のところ次のように機能することですが、引き続き機能しない可能性があります。そのため、@DaveRandom によって受け入れられた回答よりもこれを推奨することは決してありません。むしろ、この回答をここに含めて、将来他の人がこれを読んで、SimpleXMLElement の方法を探す時間を節約し、DaveRandom の DOM ベースのアプローチを使用できるようにします :-)

パーサーを「だまして」、g:要素名から名前空間プレフィックスを削除しないようにすることができます。たとえば、実際のプレフィックスの前に「ゴミ」プレフィックスを配置します"blah:g:condition"

属性プレフィックスで使用するためのこの回答のバリエーションを見てきましたが、要素プレフィックスでは使用しません。そして、それらはすべて、完全修飾名スペースを使用して 3 番目のパラメーターとして渡すことを示唆しているように見え"xmlns:yourPrefix:yourAttribute"ますが、実際には (少なくとも、私自身の個人的なテストから) xmlns:、コロンの前の部分はほとんど何でも (空白を含む!) :、しかし、その最初のコロンの前に何かがなければなりません。つまり、機能し":g:condition"ません。また、名前空間とプレフィックスを宣言するノードを実際に作成しない限り、レンダリングされた XML は無効になります (つまり、要素に対してハッキングした名前空間プレフィックスには宣言がありません)。

したがって、元のコードに基づいて、次のことを行います。また、ルート ノード宣言で名前空間が明示的に追加されていることにも注意してください (ただし、これはおそらく API を介して行うことができますが、わざわざする必要はありません)。

$xml = new SimpleXMLElement('<rss xmlns:g="http://base.google.com/ns/1.0" />'); // May as well chuck the google ns in the root element declaration here, while we're at it, rather than adding it via a separate attribute.
$xml->addAttribute('version', '2.0'); 
// $xml->addAttribute('hack:xmlns:g','http://base.google.com/ns/1.0'); //Or could do this instead...

$xml->addChild('channel');
$xml->channel->addChild('title', 'Removed');
$xml->channel->addChild('description', 'Removed');
$xml->channel->addChild('link', 'Removed');

foreach ($products as $product) {
    $item = $xml->channel->addChild('item');
    $item->addChild('title', htmlspecialchars($product['title']));
    $item->addChild('description', htmlspecialchars($product['title']));
    $item->addChild('link', $product['url']);
    $item->addChild('hack:g:id', $product['product_id']);
    $item->addChild('hack:g:price', $product['price_latest']);
    $item->addChild('hack:g:brand', $product['range']);
    $item->addChild('hack:g:condition', 'new');
    $item->addChild('hack:g:image_link', $product['image']);
}
于 2013-05-27T09:53:51.113 に答える
7

Here is an example of how to do this using DOM:

<?php

    $nsUrl = 'http://base.google.com/ns/1.0';

    $doc = new DOMDocument('1.0', 'UTF-8');

    $rootNode = $doc->appendChild($doc->createElement('rss'));
    $rootNode->setAttribute('version', '2.0');
    $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:g', $nsUrl);

    $channelNode = $rootNode->appendChild($doc->createElement('channel'));
    $channelNode->appendChild($doc->createElement('title', 'Removed'));
    $channelNode->appendChild($doc->createElement('description', 'Removed'));
    $channelNode->appendChild($doc->createElement('link', 'Removed'));

    foreach ($products as $product) {
        $itemNode = $channelNode->appendChild($doc->createElement('item'));
        $itemNode->appendChild($doc->createElement('title'))->appendChild($doc->createTextNode($product['title']));
        $itemNode->appendChild($doc->createElement('description'))->appendChild($doc->createTextNode($product['title']));
        $itemNode->appendChild($doc->createElement('link'))->appendChild($doc->createTextNode($product['url']));
        $itemNode->appendChild($doc->createElement('g:id'))->appendChild($doc->createTextNode($product['product_id']));
        $itemNode->appendChild($doc->createElement('g:price'))->appendChild($doc->createTextNode($product['price_latest']));
        $itemNode->appendChild($doc->createElement('g:brand'))->appendChild($doc->createTextNode($product['range']));
        $itemNode->appendChild($doc->createElement('g:condition'))->appendChild($doc->createTextNode('new'));
        $itemNode->appendChild($doc->createElement('g:image_link'))->appendChild($doc->createTextNode($product['image']));
    }

    echo $doc->saveXML();

See it working

于 2012-12-20T12:10:54.197 に答える