2012-11-04 140 views
5
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/'); 

從我的理解他們的行爲像文檔定義,並需要識別某些XML元素。什麼是DomDocument命名空間?

PHP實際上是否向該URL發出請求並驗證該元素是否存在於文檔定義中?

因爲該網址顯示404 not found頁面:(

$result = $xpath->evaluate('string(//atom:entry[3]/slash:comments)'); 

難道這就是爲什麼我得到一個空字符串的原因,而試圖從RSS源獲取<slash>元素的值?

回答

5
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/'); 

據我瞭解,他們像文件的定義,並要求識別某些XML元素。

PHP實際上是否向該URL發出請求並驗證該元素是否存在於文檔定義中?


也就是說URI標識XML namespace,表示XML詞彙表。這樣的命名空間被設計爲使用具有不同含義的相同術語來處理不同的上下文。對於命名空間,單個XML文件可以包含具有相同「名稱」的標籤和屬性,這些標籤和屬性均通過前綴進行限定。例如,你可以有一個XML文件是這樣的:

<html xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:human="http://sample.xml.com/Human"> 
    <title>John Smith measures.</title> 
    <body> 
    <human:name>John</human:name> <human:surname>Smith</human:surname> 
    is <human:height unit="feet">6</human:height> feet tall. 
    </body> 
</html> 

在這樣內容的「人」的前綴,用來標記從http://sample.xml.com/Human命名空間和空字符串元素(即默認前綴)使用標記來自http://www.w3.org/1999/xhtml命名空間的元素。這些URI是名稱空間標識符,而不是模式位置(可以用DOCTYPE declarationXML Schema instance表示)。在命名空間URI標識的位置提供適當的命名空間文檔是一種很好的做法,但這不是必需的(實際上,xhtml命名空間URI指向相關的W3C文檔,但是您正在尋找的RSS擴展沒有) 。

不過請注意,這兩個resolveExternalsvalidateOnParse會影響下載的目標XML DTD中提及或模式定義的,但命名空間的文檔。絕不會,任何解析器都會下載這樣的文檔,因爲它是供人類使用的。

$result = $xpath->evaluate('string(//atom:entry[3]/slash:comments)'); 

難道這是原因,我得到一個空字符串,而試圖獲取元素從一個RSS源的價值?


首先,檢查源XML包含正確xmlns聲明和它所包含的第三原子條目(注意,所述第三內部的<slash:comments>節點,因爲的xpath索引是一個基於,因此//atom:entry[1]意味着每個條目是其自己的父節點中的第一個,//atom:entry[2]第二個等等)。
如果是這樣,我懷疑你忘記了註冊原子命名空間。
嘗試這樣的事情(改編自用戶的貢獻DOMXPath::registerNamespace文檔):

$doc = new DOMDocument; 
$doc->loadXML($xml); // your xml string here 
$xpath = new DOMXPath($doc); 

$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom"); 
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/'); 

$result = $xpath->evaluate('string(//atom:entry[3]/slash:comments)'); 

你可以看到在http://codepad.org/JX8RpaKu

這個運行事實上,要使用合格的XPath,您需要註冊的默認命名空間太。

1

如果您想檢索命名空間節點的內容,你有沒有試過getElementsByTagNameNS

$dom - new DOMDocument($url); 
$slashEls = $dom->getElementsbyTagNameNS('slash', 'slash'); // Assuming the element is <slash:slash> in the XML 
foreach($slashEls as $slash) { 
    // ... 
} 
+0

它返回一個空的DOMNodeList ... –

2

您有很多問題。我會嘗試一個解決這些問題之一:

$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/'); 

據我瞭解,他們像文件的定義,並要求識別某些XML元素。

是的,只要你有一個帶有命名空間的XML文檔,那麼每個元素都可以在它自己的命名空間中。

如果你想訪問自己命名空間中的元素,那麼是的,你需要命名空間來標識它們。例如。在Xpath表達式中。

在PHP中,XML命名空間受到DOMDocument和其他基於XML的XML擴展的支持。

PHP實際上是否向該URL發出請求並驗證該元素是否存在於文檔定義中?

號,區號,比如你給:

$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/'); 

PHP將請求URL。你已經注意到URL是空的/給404,所以你可能想知道這是什麼。該URL實際上是一個URI。這是不同的是,標識符定位器

The URI Pill: Can be URL or URN

對XML命名空間的,沒有什麼需要被定位。命名空間只需要被識別。因此,一個有效的XML名稱空間可以用任何URI來表示。例如,fantasy:space是一個有效的URI,並且完全限定了要求來指定XML名稱空間。但是當你在瀏覽器中輸入時,你甚至不會得到任何服務器響應(你的瀏覽器不知道「幻想」是什麼)。

所以,你得到的404是不是,爲什麼斜槓是空的,你的XPath計算的原因:

$result = $xpath->evaluate('string(//atom:entry[3]/slash:comments)'); 

你爲什麼在這裏得到一個空字符串的原因是不同的。請參閱Xpath表達式:

string(//atom:entry[3]/slash:comments) 

這就是要求節點集的字符串值。已指定的節點設置爲:

//atom:entry[3]/slash:comments 

Getting a string of a nodeset在PHP的DOMDocument意味着:

節點集通過返回在節點集是首先在string-value of the node轉換爲字符串文件順序。如果節點集爲空,則返回空字符串。

作爲節點是一個元素,的the element node字符串值是指:

元素節點的字串值是的所有文本節點的後代的字符串值的串聯元素節點按文檔順序排列。

所以在這裏有兩個解釋爲什麼你得到一個空字符串:或者節點集是空的或者元素的字符串值只是一個空字符串。

您可以快速瞭解內部節點的數量的節點集合使用count() function

$result = $xpath->evaluate('count(//atom:entry[3]/slash:comments)'); 

然後應該給你一個更好的主意,這兩種情況是如此。由於您尚未共享源XML,因此不能說爲什麼具體而言,但我認爲它不包含節點。看到來源應該很容易澄清這一點。

在此之前,我只能猜測您可能解析了不包含<atom:entry>元素但僅包含<item>元素的RSS 2提要。看我的例子:

$feed = 'http://hakre.wordpress.com/feed/'; 

$doc = new DOMDocument(); 
$doc->load($feed); 
$xpath = new DOMXPath($doc); 

echo $xpath->evaluate('string(//item[3]/slash:comments)'); # 1 

它輸出值「1」作爲第三項的評論計數。這是一個標準的WordPress博客的飼料。 I have put this online as an interactive example, so you can see it in action and enter your feed URL

BTW:如果您加載了XML之後創建DOMXPath對象,你不需要,只要你知道哪些前綴文檔中使用註冊的命名空間的URI。這就是爲什麼在這個例子中我沒有註冊任何名稱空間URI。