[英]ignore namespace with xpath in php
我想从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拉“ // title”时,一切正常,并且我收到了两个标题。
但是当我使用以下php时:
$xml = simplexml_load_file('articles.xml');
$result = $xml->xpath('//title');
var_dump($result);
结果数组为空。
我已经检查了许多类似的问题,并发现如果使用相同的URL设置registerXPathNamespace,它将可以使用。 但是,我正在阅读的XML来自几个外部来源,这些来源带有不同的软件(以上只是一个可能的示例)。 它们可能随时更改。 因此,每次打开XML时,我都需要读出URL并将其放入registerXPathNamespace中。 使它起作用的另一种方法是从XML中剥离xmlns。 如果我想要做的就是不管名称空间是什么,都提取“ title”(和其他一些)标记,那么这两个选项似乎都非常复杂。
有没有一种简单的方法告诉xpath忽略名称空间? (如果没有办法忽略它,那么避免更改URL问题的最简单,持久的解决方案是什么?)
到目前为止,我正在使用硬编码
foreach ($xml->page as $page) {
$title = $page->title;
//[... do something ...]
}
哪个有效。 但是我认为xpath会很方便(更灵活,不硬编码,更耐用),并想尝试一下。
您可以通配名称空间,例如//*:title
您可以从文档中获取名称空间,然后从中注册默认名称空间。 由于默认名称空间以空白键结尾,这有点麻烦,但这就是为什么从数组中获取第一个值然后使用它有点费解的原因。
因此,代码类似于:
$xml = simplexml_load_file('articles.xml');
$ns = $xml->getDocNamespaces();
$xml->registerXPathNamespace('def', array_values($ns)[0]);
$result = $xml->xpath('//def:title');
var_dump($result);
尽管选择的注册默认名称空间的解决方案有效,但它也要求我似乎毫无理由地使我的xpath查询混乱。 在我的特殊情况下,我怀疑还有许多其他情况,从文档中完全删除名称空间会更有帮助。 不幸的是,并没有出现任何的方式来做到这一点使用DOM工具在PHP,所以我不得不求助于正则表达式。 我要说的是, 我真的很讨厌这样做,因为我是一再因为使用正则表达式来操纵XML和HTML的人而不断地追求他人。
无论如何,这对我有用:
$xml = file_get_contents('my_document.xml');
$xml = preg_replace('/(xmlns|xsi)[^=]*="[^"]*" ?/i', '', $xml);
$doc = simplexml_load_string($xml);
而且,现在您可以根据需要查询xpath,而无需命名空间前缀:
$result = $xml->xpath('//title');
根据文档的不同,这可能不是一个好主意,尤其是在元素上有名称空间前缀的情况下,但是在许多基本情况下,它就可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.