【问题标题】:PHP's SimpleXML: How to use colons in namesPHP 的 SimpleXML:如何在名称中使用冒号
【发布时间】:2011-03-02 10:05:29
【问题描述】:

我正在尝试使用 SimpleXML 生成一个 RSS Google Merchant。

谷歌给出的示例是:

<?xml version="1.0"?>
<rss version="2.0" 
xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>The name of your data feed</title>
<link>http://www.example.com</link>
<description>A description of your content</description>
<item>
<title>Red wool sweater</title>
<link> http://www.example.com/item1-info-page.html</link>
<description>Comfortable and soft, this sweater will keep you warm on those cold winter nights.</description>
<g:image_link>http://www.example.com/image1.jpg</g:image_link> <g:price>25</g:price> <g:condition>new</g:condition> <g:id>1a</g:id>
</item>
</channel>
</rss>

我的代码有这样的东西:

$product->addChild("g:condition", 'new');

生成:

<condition>new</condition>

我在网上看到我应该改用:

$product->addChild("g:condition", 'new', 'http://base.google.com/ns/1.0');

现在生成:

<g:condition xmlns:g="http://base.google.com/ns/1.0">new</g:condition>

这对我来说似乎很违反直觉,因为现在“xmlns”声明几乎出现在我的 RSS 提要的每一行,而不是根元素中只有一次。

我错过了什么吗?

【问题讨论】:

    标签: php xml rss simplexml


    【解决方案1】:

    正如@ceejayoz 所说,您需要将“http://base.google.com/ns/1.0”命名空间添加到根节点,以便 SimpleXML 知道命名空间已经被声明并且不会发出重复的前缀绑定。

    我认为您可能需要阅读tutorial on XML Namespaces,因为我不确定您是否真的理解“g:”在这里的作用。

    这是一个更完整的例子。 XML:

    $xml = <<<EOT 
    <?xml version="1.0"?> 
    <rss version="2.0" xmlns:g="http://base.google.com/ns/1.0"> 
      <channel> 
        <title>The name of your data feed</title> 
        <link>http://www.example.com</link> 
        <description>A description of your content</description> 
        <item> 
          <title>Red wool sweater</title> 
          <link> http://www.example.com/item1-info-page.html</link> 
          <description>Comfortable and soft, this sweater will keep you warm on those cold winter nights.</description> 
          <g:image_link>http://www.example.com/image1.jpg</g:image_link> 
          <g:price>25</g:price> 
          <g:id>1a</g:id> 
        </item> 
      </channel> 
    </rss> 
    EOT 
    ; 
    

    代码:

    $rss = new SimpleXMLElement($xml); 
    $NS = array( 
        'g' => 'http://base.google.com/ns/1.0' 
    ); 
    $rss->registerXPathNamespace('g', $NS['g']); 
    $product = $rss->channel->item[0]; // example 
    
    // Use the complete namespace. 
    // Don't add "g" prefix to element name--what prefix will be used is 
    // something SimpleXML takes care of. 
    $product->addChild('condition', 'new', $NS['g']); 
    
    echo $rss->asXML(); 
    

    我通常使用这种模式来轻松处理命名空间:

    $rss = new SimpleXMLElement($xml); 
    $NS = array( 
        'g' => 'http://base.google.com/ns/1.0' 
        // whatever other namespaces you want 
    ); 
    // now register them all in the root 
    foreach ($NS as $prefix => $name) { 
        $rss->registerXPathNamespace($prefix, $name); 
    } 
    // Then turn $NS to an object for more convenient syntax 
    $NS = (object) $NS; 
    // If I need the namespace name later, I access like so: 
    $element->addChild('localName', 'Value', $NS->g); 
    

    【讨论】:

    • 你有new SimpleXMLElement($xml),你没有显示$xml 是什么。这就是我最终使用的(没有它就无法工作):'&lt;rss xmlns:g="http://base.google.com/ns/1.0"&gt;&lt;/rss&gt;'
    • 仔细阅读:答案中的第一个代码块以$xml = 开头,计算结果为一个xml 字符串。
    • 像魅力一样工作!感谢您提供详细的解决方案!
    • 我觉得这里有点误会。顾名思义,registerXPathNamespace 仅在使用 XPath 进行查询时使用,与将名称空间添加到您正在生成的文档中无关。
    【解决方案2】:

    这样就可以了:

    $product->addChild('xmlns:g:condition', 'new'); 
    

    【讨论】:

    • 这对我有用,我觉得实际上回答了这个问题 - 关于命名空间和拥有它们的父节点的其他帖子很棒,但我的文件已经有父命名空间,我只需要添加“ xmlns:" 让它正确添加节点。谢谢!
    • 这依赖于 XML 库中的一个怪癖(错误),它没有注意到您对标签名称使用了非法语法。它实际上并没有以任何方式正确处理命名空间。
    【解决方案3】:

    您需要将该命名空间添加到父节点,最好是根rss 之一,以便子节点可以继承它,而不必每次都显式指定它。

    【讨论】:

    • 我试过$xml = new SimpleXMLElement('&lt;rss&gt;&lt;/rss&gt;'); $xml-&gt;addAttribute('version','2.0'); $xml-&gt;registerXPathNamespace('g', 'http://base.google.com/ns/1.0'); 然后后来:$product-&gt;addChild("g:condition", 'new'); 它生成:&lt;condition&gt;new&lt;/condition&gt; 它再次跳过“g:”...
    • 您仍然需要在addChild 调用中指定命名空间。它只是不应该输出,因为根节点已经有了它。
    猜你喜欢
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 2021-05-03
    相关资源
    最近更新 更多