2011-07-08 41 views
3

真讓人氣憤,我幾乎不能說話。我已經使用SimpleXML組裝了一個RSS提要,但它現在使用名稱空間。但是,在輸出時,它始終試圖在根節點中聲明xmlns:xmlns =「」。儘管我不這樣做。SimpleXML已聲明xmlns:xmlns =「」 - 無法刪除

它開始

$rssXML->addAttribute("version", '2.0'); 
$rssXML->addAttribute("xmlns:media", "http://search.yahoo.com/mrss/", ''); 
$rssXML->addAttribute("xmlns:dcterms", "http://purl.org/dc/terms/", ''); 

並在此之後我做的: -

header("Content-Type: application/rss+xml"); 

echo $syndicationXML->asXML(); 

然而,它輸出: -

<?xml version="1.0"?> 
<rss xmlns:xmlns="" version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/"><channel>... 

我不明白這一切的命名空間聲明。這是怎麼回事?

回答

6

SimpleXML的問題在於它的addAttribute函數添加了一個屬性,而不是一個名稱空間,雖然它看起來像是做了你想要的,但它並不意味着以你使用它的方式使用。

它意味着添加一個屬於特定名稱空間(指定爲第三個參數)的值,而不是添加名稱空間本身。您最終得到xmlns:xmlns的原因是因爲SimpleXML發現在例如指定名稱xmlns:media時使用了xmlns名稱空間,因此它創建了一個空的xmlns:xmlns

這裏有兩個解決問題的方法:

1.指定在構造函數的命名空間。

$rssXML = new SimpleXMLElement('<rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/" />'); 
$rssXML->addAttribute('version', '2.0'); 

2.使用preg_replace

echo preg_replace('/xmlns:xmlns=""\s?/', '', $rssXML->asXML()); 
+0

解釋的很清楚,非常有益和正確的。謝謝。 :) – waxical

0

你寫你自己想要刪除替換xmlns:xmlns=""。最好的方法是不要放在首位。

這是通過與xmlns:(其他時間)前綴 - 它在某種程度上使操作SimpleXML中的一種特殊模式 - 和提供一個空的命名空間URI(否則你居然問補充說):

$rssXML = new SimpleXMLElement('<rss/>'); 
$rssXML->addAttribute("version", '2.0'); 
$rssXML->addAttribute("xmlns:xmlns:media", "http://search.yahoo.com/mrss/"); 
$rssXML->addAttribute("xmlns:xmlns:dcterms", "http://purl.org/dc/terms/"); 
$rssXML->asXML('php://output'); 

這將創建下列輸出(美化您的閱讀樂趣):

<?xml version="1.0"?> 
<rss version="2.0" 
    xmlns:media="http://search.yahoo.com/mrss/" 
    xmlns:dcterms="http://purl.org/dc/terms/"/> 

這種「欺騙」最初是在暗示,但"Unable to add Attribute with Namespace Prefix using PHP Simplexml"是小姐在這裏。

+0

它的工作原理是因爲添加的節點是屬性而不是名稱空間聲明,「xmlns:」是屬性名稱本地部分的一部分,而不是名稱空間前綴。您可以使用任何前綴,而不僅僅是「xmlns」,因爲它會被忽略。序列化時無關緊要,但在處理對象時會有所作爲(例如,使用['SimpleXMLElement-> attributes()'](http://php.net/SimpleXMLElement.attributes)和'SimpleXMLElement- > children()'或者['SimpleXMLElement-> addChild()'](http://php.net/SimpleXMLElement.addChild))的名稱空間參數。 – outis

0

SimpleXMLElement只能間接地添加命名空間。由於只能添加元素和屬性節點,而不是名稱空間聲明,文本節點或其他節點類型,因此您必須以某種方式使用SimpleXMLElement->addAttribute()SimpleXMLElement->addChild()。後者只會向孩子添加新的命名空間,所以在這裏沒用。 addAttribute()會將名稱空間和屬性一起添加到給定元素,因此如果您刪除了該屬性,則會根據需要留下名稱空間。

沒有明顯的刪除屬性的方法,但使用unset(如「Remove a child with a specific attribute, in SimpleXML for PHP」的幾個答案中所示)可以適應任務,使用SimpleXMLElement->attributes()來獲得對該屬性的引用。

<?php 
$rssXML = new SimpleXMLElement('<rss/>'); 
$rssXML->addAttribute("version", '2.0'); 
# add a dummy attribute to get the namespace 
$rssXML->addAttribute("media:_", '', "http://search.yahoo.com/mrss/"); 
unset($rssXML->attributes('media', TRUE)[0]); 
# and again 
$rssXML->addAttribute("dcterms:_", '', "http://purl.org/dc/terms/"); 
unset($rssXML->attributes('dcterms', TRUE)[0]); 

echo $rssXML->asXML(), "\n"; 

結果:

<?xml version="1.0"?> 
<rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/" version="2.0"/> 

優勢這在增加空間聲明爲用假名字空間預謀的屬性,它會被視爲一個命名空間,而不是恰好有一些屬性是看起來像名稱中的名稱空間前綴。

var_export($rssXML->getDocNamespaces()); 

結果:

array (
    'media' => 'http://search.yahoo.com/mrss/', 
    'dcterms' => 'http://purl.org/dc/terms/', 
)