2010-10-08 69 views
3

我有一個加載xml文件的問題。我使用DOMDocument,因爲我需要函數getElementsByTagName
我使用這段代碼。 使用HTML加載DOMDocument特殊字符(php)

 
$dom = new DomDocument('1.0', 'UTF-8'); $dom->resolveExternals = false; $dom->load($_FILES["file"]["tmp_name"]);  
 
<?xml version="1.0" encoding="UTF-8"?> 
<Data> 
    <value>1796563</value> 
    <value>Verliebt! &rsquo;</value> 
</Data> 

的ErrorMessage:
警告:DOM文檔::負載()[domdocument.load]:實體 'rsquo的' 未在/ tmp/php1VRb3N,線限定:4 /網絡/ htdocs中/ BLA /上傳在線51上的.php

回答

1

你的XML解析器是不是在說謊。這是一個無效(甚至沒有格式化)的文件,你將無法加載任何東西。

rsquo是HTML中的預定義實體,但不是XML。在XML文檔中,如果您想使用除最基本的內置實體(amp,lt,gt,和apos)之外的任何內容,則必須在由<!DOCTYPE>聲明引用的DTD中定義它們。 (這是XHTML如何實現的。)

您需要找出輸入來自哪裏,並修復造成它的責任,因爲目前它不是XML。使用字符引用(&#8217;)或UTF-8編碼中的純字面字符

就好像你真的要接受輸入的這個畸形的廢話,你可以在文件做討厭的字符串替換最後一招:

$xml= file_get_contents($_FILES['file']['tmp_name']); 
$xml= str_replace('&rsquo;', '&#8217;', $xml); 
$dom->loadXML(xml); 

如果您需要爲所有非XML HTML實體做到這一點而不僅僅是rsquo這有點棘手。你可以做一個正則表達式替換:

function only_html_entity_decode($match) { 
    if (in_array($match[1], array('amp', 'lt', 'gt', 'quot', 'apos'))) 
     return $match[0]; 
    else 
     return html_entity_decode($match[0], ENT_COMPAT, 'UTF-8'); 
} 
$xml= preg_replace_callback('/&(\w+);/', 'only_html_entity_decode', $xml); 

這仍然不是很大,因爲它是要被抨擊裏面這樣的評論,CDATA節和督察地方&\w+;字符的任意序列,其中這並不意味着真正的實體參考。但是,這可能是關於你輸入這個輸入信號的最好方法。

這肯定比在整個文檔上調用html_entity_decode好,這也會弄亂任何XML實體引用,導致文檔在存在&amp;&lt;時中斷。

另一種以不同方式存在疑問的黑客將使用loadHTML()加載文檔。

+0

感謝您的幫助。 – Bendim 2010-10-09 01:19:28

2

爲了使用該實體,它必須在DTD中定義。否則,它是無效的XML。如果你沒有一個DTD,你應該在實體DOM加載XML之前解碼:

$dom->load(
    html_entity_decode(
     file_get_contents($_FILES["file"]["tmp_name"]), 
     ENT_COMPAT, 'UTF-8')); 
0

我從bobince幫助的解決方案是:

$xml= file_get_contents($_FILES['file']['tmp_name']); 
    $xml= preg_replace('/&(\w+);/', '', $xml); 
    $dom = new DomDocument(); 
    $dom->loadXML($xml); 
+0

這也將拋棄所有XML預定義的實體引用,如「&」和「<」。你確定你想這麼做嗎? – bobince 2010-10-09 01:46:45

+0

是的。在我的文件中沒有XML預定義的實體引用,如「&」或「<」。 – Bendim 2010-10-09 01:58:13