2016-01-19 70 views
0

我有此代碼樣品(全碼 here):DOM XPath查詢失敗

$raw = " (xml data) "; 

$nsURIs = array 
(
    'opf'  => 'http://www.idpf.org/2007/opf', 
    'dc'  => 'http://purl.org/dc/elements/1.1/', 
    'dcterms' => 'http://purl.org/dc/terms/', 
    'xsi'  => 'http://www.w3.org/2001/XMLSchema-instance', 
    'ncx'  => 'http://www.daisy.org/z3986/2005/ncx/', 
    'calibre' => 'http://calibre.kovidgoyal.net/2009/metadata' 
); 

$dom = new \DOMDocument(); 
$dom->loadXML($raw,LIBXML_NOBLANKS); 

$metadata = $dom->getElementsByTagName('metadata')->item(0);   #metadata 

$xpath = new \DOMXPath($dom); 
foreach($nsURIs as $key => $ns) $xpath->registerNamespace($key, $ns); 

$query = array(); 
$query[] = '//dc:identifier';           #00 
$query[] = '//dc:identifier[. = "9780439554930"]';      #01 
$query[] = '//dc:identifier[@opf:scheme="ISBN"]';      #02 
$query[] = '//dc:identifier[starts-with(@opf:scheme,"I")]';   #03 
$query[] = '//dc:identifier[contains(@opf:scheme,"SB")]';    #04 
$query[] = '//dc:identifier[ends-with(@opf:scheme,"N")]';    #05 Unregistered 
$query[] = '//dc:identifier["IS" = substring(@opf:scheme, 0, 2)]';  #06 Fails 
$query[] = '//dc:identifier[contains(.,"439")]';      #07 
$query[] = '//dc:identifier[@*="ISBN"]';        #08 
$query[] = '//dc:date[contains(@*, "cation")]';      #09 
$query[] = '//dc:*[contains(@opf:*, "and")]';       #10 Wrong Result 
$query[] = '//dc:*[contains(@opf:file-as, "and")]';     #11 
$query[] = '//dc:*[contains(@opf:*, "ill")]';       #12 
$query[] = '//dc:contributor[@opf:role and @opf:file-as]';    #13 
$query[] = '//dc:subject[contains(.,"anta") and contains(.,"Urban")]'; #14 
$query[] = '//dc:subject[text() = "Fantasy"]';       #15 

for($i=0; $i<count($query); $i++) 
{ 
    $result = $xpath->evaluate($query[$i]); 
    echo sprintf("[%02d] % 2d %s\n", $i, $result->length, $query[$i]); 
} 

查詢#5失敗由於未登記的功能;查詢#6失敗(0結果全爲1)並且查詢#10生成1個項目而不是2個(如在以下查詢#11處正確生成)。 相同的結果在$metadata上下文上執行查詢。

this question我發現未註冊ends-with一種替代方案:

$query[] = '//dc:identifier["N" = substring(@opf:scheme, string-length(@opf:scheme) - string-length("N"))]'; 

但即使這樣黑客失敗...

任何人有任何建議或替代方案?

+2

究竟是什麼問題?你想達到什麼目的? – har07

+0

我的實現是檢查XPath是否正常工作。問題是:提供的代碼失敗是XPath錯誤還是因爲我的錯誤?在xml代碼中,有兩個節點的屬性名爲'opf:file-as',文本'和':爲什麼查詢10返回1個項目(不正確)並且查詢#11返回2個項目(確定)?並且繞過未註冊的'ends-with'函數(在引用的問題中標記爲工作)是不正確的?或者我不得不忘記'結束 - 查詢? 如果我不清楚,我很抱歉。關於'ends-with()'函數的 – fusion3k

+0

,你應該讀[this](http://stackoverflow.com/questions/402211/how-to-use-xpath-function-in-a-xpathexpression-instance-編程/ 402357#402357)(回答你鏈接到的重複問題) – har07

回答

1

關於#06 Fails

//dc:identifier["IS" = substring(@opf:scheme, 0, 2)] 

說明:從1代替0

XPath索引開始,所以subsstring()這裏正確的參數是:

//dc:identifier["IS" = substring(@opf:scheme, 1, 2)] 

關於#10 Wrong Result

//dc:*[contains(@opf:*, "and")] 

說明:

當傳送多個值中的XPath 1.0功能參數,只有第一個值將被評估。所以在這種情況下,只能用前綴opf第一屬性進行評估,因此下面的元素不計數:

<dc:contributor opf:role="ill" opf:file-as="GrandPré, Mary">Mary GrandPré</dc:contributor> 

避免這個問題,你應該改變的XPath是如下:

//dc:*[@opf:*[contains(., "and")]] 
+0

是的!非常感謝! – fusion3k