Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在php中忽略带有xpath的命名空间_Php_Xpath_Xml Namespaces - Fatal编程技术网

在php中忽略带有xpath的命名空间

在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.

我想从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>
结果数组为空

我已经检查了许多类似的问题,发现如果我使用相同的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');