在php中忽略带有xpath的命名空间
我想从xml文件中提取一些标记。xml文件可能如下所示:在php中忽略带有xpath的命名空间,php,xpath,xml-namespaces,Php,Xpath,Xml Namespaces,我想从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.
<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>
结果数组为空
我已经检查了许多类似的问题,发现如果我使用相同的URL设置registerXPathNamespace,它会起作用。然而,我正在阅读的XML来自多个具有不同软件的外部源(上面只是一个可能的示例)。他们随时可能改变。因此,每次打开XML时,我都需要读取URL并将其放入registerXPathNamespace。另一种可行的方法是从XML中剥离XMLN。如果我只想提取“title”(和其他一些)标记,而不管名称空间是什么,那么这两个选项似乎都相当复杂
有没有简单的方法告诉xpath忽略名称空间?
(如果没有办法忽略它:什么是避免更改URL问题的最简单和持久的解决方案?)
到目前为止,我使用的是硬编码
foreach ($xml->page as $page) {
$title = $page->title;
//[... do something ...]
}
这很有效。但我认为xpath会很方便(更灵活,而不是硬编码,更持久),并想尝试一下。您可以从文档中获取名称空间,然后从这些名称空间中注册默认名称空间。这有点麻烦,因为默认名称空间以一个空键结束,但这就是为什么从数组中获取第一个值然后使用它有点假 因此,代码类似于:
$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查询弄得杂乱无章。在我的特殊情况下(我怀疑还有很多其他情况),从文档中完全删除名称空间更有帮助。不幸的是,在php中使用DOM工具似乎没有办法做到这一点,所以我不得不求助于正则表达式。我要说的是,我真的很讨厌这样做,因为我是那些反复批评别人用正则表达式操纵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');
根据您的文档,这可能是一个非常糟糕的主意,尤其是如果元素上有名称空间前缀,但在许多基本情况下,它可以正常工作。我更希望通配符解决方案完全忽略名称空间,但由于名称空间通配符在PHP中不起作用,我将使用您的解决方案。
$result = $xml->xpath('//title');