[英]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.