我想从xml文件中提取一些标签。 xml文件可能如下所示:
<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="de">
[... some more tags ...]
<page>
<title>Title 1</title>
[... some more tags ...]
</page>
<page>
<title>Title 2</title>
[... some more tags ...]
</page>
</mediawiki>
我用的时候 https://www.freeformatter.com/xpath-tester.html 拉“//标题”一切正常,我收到两个标题。
但是当我使用以下php时:
$xml = simplexml_load_file('articles.xml');
$result = $xml->xpath('//title');
var_dump($result);
结果数组为空。
我已经检查了许多类似的问题,发现如果我使用相同的URL设置registerXPathNamespace,它会起作用。但是,我正在阅读的XML来自几个使用不同软件的外部源(以上只是一个可能的例子)。他们可能随时改变。因此,每次打开XML时,我都需要读出URL并将其放入registerXPathNamespace。使其工作的另一个选择是从XML中剥离xmlns。如果我想要做的就是提取“标题”(和其他一些)标签,无论名称空间是什么,这两个选项似乎都非常复杂。
是否有一种简单的方法可以告诉xpath忽略命名空间? (如果没有办法忽略它:什么是最简单和持久的解决方案,以避免更改URL的问题?)
到目前为止,我正在使用硬编码
foreach ($xml->page as $page) {
$title = $page->title;
//[... do something ...]
}
哪个有效。但是我认为xpath会很方便(更灵活,不是硬编码,更耐用)并且想尝试一下。
答案 0 :(得分:0)
您可以通配符名称空间,例如//*:title
答案 1 :(得分:0)
您可以从文档中获取名称空间,然后从这些名称中注册默认名称空间。由于默认命名空间以空白键结束,这有点令人痛苦,但这就是为什么从数组中获取第一个值然后使用它有点软糊涂。
所以代码类似于:
$xml = simplexml_load_file('articles.xml');
$ns = $xml->getDocNamespaces();
$xml->registerXPathNamespace('def', array_values($ns)[0]);
$result = $xml->xpath('//def:title');
var_dump($result);
答案 2 :(得分:0)
尽管选择的注册默认名称空间的解决方案可行,但这还要求我似乎毫无理由地弄乱了xpath查询。在我的特殊情况下,我怀疑还有许多其他情况,从文档中完全删除名称空间会更有帮助。不幸的是,没有出现可以使用php中的DOM工具来做到这一点,所以我不得不求助于正则表达式。我要说的是,我真的很讨厌这样做,因为我是一再因为使用正则表达式来操纵XML和HTML的人而不断地追求他人的人。
无论如何,这对我有用:
$xml = file_get_contents('my_document.xml');
$xml = preg_replace('/(xmlns|xsi)[^=]*="[^"]*" ?/i', '', $xml);
$doc = simplexml_load_string($xml);
voilà,现在您可以根据需要查询xpath,而无需命名空间前缀:
$result = $xml->xpath('//title');
根据您的文档,这可能不是一个好主意,尤其是在元素上有名称空间前缀的情况下,但是在许多基本情况下,它就可以正常工作。