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;
输出:
1
除了上面解释的命名空间问题之外,您需要重新检查XPath,即$query2
,确保它完全对应于XML中目标元素的位置。