2016-01-14 10 views
2

我無法檢索文件(S)像this one使用XPath結果:PHP/XPath查詢的NCX(EPUB)失敗

<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1"> 
    <head> 
     <meta name="dtb:uid" content="RT8513Z9UM0NLKLF8QX9QDJ3E6ZFL2"/> 
     <meta name="dtb:depth" content="3"/> 
    </head> 
    <docTitle> 
     <text>Document Title</text> 
    </docTitle> 
    <navMap> 
     <navPoint id="navPoint-1" playOrder="1"> 
      <navLabel> 
       <text>Section with no subsection</text> 
      </navLabel> 
      <content src="text/content001.xhtml"/> 
     </navPoint> 
     <navPoint id="navPoint-2" playOrder="2"> 
      <navLabel> 
       <text>TOC entry name Section title 
       </text> 
      </navLabel> 
      <content src="text/content001.xhtml#heading_id_3"/> 
      <navPoint id="navPoint-3" playOrder="3"> 
       <navLabel> 
        <text>Section entry name.</text> 
       </navLabel> 
       <content src="text/content002.xhtml"/> 
      </navPoint> 
      <navPoint id="navPoint-4" playOrder="4"> 
       <navLabel> 
        <text>Introduction.</text> 
       </navLabel> 
      </navPoint> 
     </navPoint> 
    </navMap> 
</ncx> 

執行以下代碼:

$ncx = new DOMDocument(); 
$ncx->preserveWhiteSpace = false; 
$ncx->load('/path/to/file'); 

$xpath = new DOMXPath($ncx); 

$query1 = 'namespace::*'; 
$result = $xpath->query($query1); 
echo $result->length . PHP_EOL; 

$query2 = '/ncx/navMap/navLabel/text[. = "Introduction."]'; 
$result = $xpath->query($query2); 
echo $result->length . PHP_EOL; 

$head = $ncx->getElementsbyTagName('head')->item(0); 

$query3 = 'head/meta[@name="dtb:depth"]'; 
$result = $xpath->query($query3, $head); 
echo $result->length . PHP_EOL; 

$query4 = 'meta[@name="dtb:depth"]'; 
$result = $xpath->query($query4, $head); 
echo $result->length . PHP_EOL; 

$query1產生有效的結果。 任何人都可以提示錯誤在哪裏?

謝謝

回答

1

核心問題是您的XPath沒有考慮XML命名空間。你的XML已經默認命名空間中定義的位置:

<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1"> 

所以ncx元素,它是沒有前綴的後裔在默認命名空間。在默認命名空間查詢元素,你需要一個前綴映射到命名空間和使用前綴在你的XPath,例如:

//map prefix "d" to the default namespace uri 
$xpath->registerNamespace("d", "http://www.daisy.org/z3986/2005/ncx/"); 
..... 
$head = $ncx->getElementsbyTagName('head')->item(0); 
..... 
//use the registered prefix properly in the XPath 
$query4 = 'd:meta[@name="dtb:depth"]'; 
$result = $xpath->query($query4, $head); 
echo $result->length . PHP_EOL; 

eval.in demo

輸出:

1 

除了上面解釋的命名空間問題之外,您需要重新檢查XPath,即$query2,確保它完全對應於XML中目標元素的位置。