PHP/XPath查询的NCX(EPUB)失败

问题描述:

我无法检索文件(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产生有效的结果。 任何人都可以提示错误在哪里?

谢谢

核心问题是您的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中目标元素的位置。