使用SimpleXML编写XML文件时如何使用命名空间

Mar*_*ean 5 php simplexml xml-namespaces

我正在使用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>
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

<?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']);
}
Run Code Online (Sandbox Code Playgroud)

我如何介绍g的命名空间,无论是xmlns在根声明rss元素,然后作为前缀id,price,brand,conditionimage_link在每个item元素?

Sep*_*ter 10

可以使用SimpleXMLElement接口完成.恕我直言,这是最狡猾的订单的黑客,但它现在有效.

关键的一点是它的工作原理如下,现在,但可能无法继续工作.因此,我不会推荐@DaveRandom接受的答案.相反,我在这里包含这个答案,以便将来的其他人可以阅读这个并节省一些时间来搜索SimpleXMLElement方法,并且只需使用DaveRandom基于DOM的方法:-)

您可以"欺骗"解析器以阻止它从g:您的元素名称中删除您的名称空间前缀,方法是在您的真实前缀之前添加"垃圾"前缀,例如"blah:g:condition".

我已经看到这个答案的变体用于属性前缀,但不是元素前缀.那些似乎都建议使用"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']);
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*dom 7

以下是使用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();
Run Code Online (Sandbox Code Playgroud)

看它工作

  • 谢谢,戴夫.完善!我自己写了一个与你的非常相似的工作解决方案:https://gist.github.com/4344973 (2认同)