2010-12-22 81 views
0

我編寫了一個小PHP腳本來編輯站點新聞XML文件。 我使用DOM來操縱XML(加載,寫入,編輯)。PHP:將非英文字符寫入XML - 編碼問題

在編寫英文字符時工作正常,但在編寫非英文字符時,PHP在嘗試加載文件時會引發錯誤。

如果我手動輸入非英語字符到文件 - 它的加載完美的罰款,但如果PHP寫的非英語字符,雖然我指定的UTF-8編碼的編碼出錯。

任何幫助表示讚賞。

更新:與有用的答案,它解決了(閱讀下文)。

錯誤:

警告:DOM文檔::負載() [domdocument.load]:實體 '次' 不 在文件路徑定義

警告:DOM文檔::負載() [ domdocument.load]:輸入不是 正確的UTF-8,表示編碼! 字節:0x91值爲0x26 0x74×69的文件路徑

這裏是負責加載和保存文件(不言自明)功能:

function get_tags_from_xml(){ 
// Load news entries from XML file for display 
    $errors = Array(); 

    if(!$xml_file = load_news_file()){ 
    // Load file 
     // String indicates error presence 
     $errors = "file not found"; 
     return $errors; 
    } 
    $taglist = $xml_file->getElementsByTagName("text"); 
    return $taglist; 
} 
function set_news_lang(){ 
// Sets the news language 
    global $news_lang; 

    if($_POST["news-lang"]){ 
     $news_lang = htmlentities($_POST["news-lang"]); 
    } 
    elseif($_GET["news-lang"]){ 
     $news_lang = htmlentities($_GET["news-lang"]); 
    } 
    else{ 
     $news_lang = "he"; 
    } 
} 
function load_news_file(){ 
// Load XML news file for proccessing, depending on language 
    global $news_lang; 

    $doc = new DOMDocument('1.0','utf-8'); 
    // Create new XML document 
    $doc->load("news_{$news_lang}.xml"); 
    // Load news file by language 
    $doc->formatOutput = true; 
    // Nicely format the file 

    return $doc; 
} 
function save_news_file($doc){ 
// Save XML news file, depending on language 
    global $news_lang; 

    $doc->saveXML($doc->documentElement); 
    $doc->save("news_{$news_lang}.xml"); 
} 

這裏是寫XML代碼(添加新聞):

<?php ob_start()?> 
<?php include("include/xml_functions.php")?> 
<?php include("../include/functions.php")?> 
<?php get_lang();?> 
<?php 
//TODO: ADD USER AUTHENTICATION! 
if(isset($_POST["news"]) && isset($_POST["news-lang"])){ 
    set_news_lang(); 

    $news = htmlentities($_POST["news"]); 

    $xml_doc = load_news_file(); 
    $news_list = $xml_doc->getElementsByTagName("text"); 
    // Get all existing news from file 

    $doc_root_element = $xml_doc->getElementsByTagName("news")->item(0); 
    // Get the root element of the new XML document 
    $new_news_entry = $xml_doc->createElement("text",$news); 
    // Create the submited news entry 

    $doc_root_element->appendChild($new_news_entry); 
    // Append submited news entry 
    $xml_doc->appendChild($doc_root_element); 

    save_news_file($xml_doc); 

    header("Location: /cpanel/index.php?lang={$lang}&news-lang={$news_lang}"); 
} 
else{ 
    header("Location: /cpanel/index.php?lang={$lang}&news-lang={$news_lang}"); 
} 
?> 
<?php ob_end_flush()?> 

更新:根據您提供的有用的答案,它的解決: 提交表單的值不是英語,它包含了一些HTML實體, 我在POST上使用了htmlentities(),這使得非英文字符串不可讀。 替換htmlentities()htmlspecialchars(),它的作品很神奇。

結論:htmlentities()可以破壞非英文字符串。

+0

請注意`htmlspecialchars()` - 我發現除了修復主要實體之外,它還可以打擊一些非Unicode字符(即ASCII/1252等價)。 `str_replace()`通常更安全:) – 2010-12-22 10:35:19

回答

2

字符編碼總是一件麻煩事。確保包含表單的頁面,加載到$ dom的xml和php文件本身也是utf-8編碼,或者相應地進行轉換。否則,你的所有字符串將不會,並且將它們作爲utf-8處理將不起作用。

試試這個:回聲原始的XML消息到一個空白頁。然後在瀏覽器中切換頁面編碼以查看哪一個正確顯示字符。從表單中檢索輸入後重復此操作獲取$ news。這通常提供了編碼出錯的地方的線索。

+0

謝謝!我回應消息,它出來了一堆胡言亂語。添加新條目的過程在沒有任何HTML的分離文件上執行,只有PHP。我猜想,我需要以某種方式在該文件上設置編碼。或者它也可能在POST中出錯。 – Dean 2010-12-22 09:30:49

+0

好吧我也試着在代碼裏面給$ news分配一個非英文字符串值,並且它回顯得很好,我猜測它沒有通過POST正確傳輸。 – Dean 2010-12-22 09:52:52

1

很難診斷的準確問題,而拉動應用除了多一點,但是這是一個很好的線索:

警告:DOM文檔::負載()[domdocument.load]:實體「時代'未在文件路徑中定義

XML通常不喜歡像&times;這樣的HTML實體。保證工作的唯一實體是&lt;,&gt;,&amp;&quot;

改爲使用數字實體。因此對於×,請使用&#xD7;等。

這裏有一個快速和骯髒的伎倆您可以在通話後添加到html_entities

foreach(array('quot'=>34,'amp'=>38,'lt'=>60,'gt'=>62,'OElig'=>338,'oelig'=>339, 
'Scaron'=>352,'scaron'=>353,'Yuml'=>376,'circ'=>710,'tilde'=>732,'ensp'=>8194, 
'emsp'=>8195,'thinsp'=>8201,'zwnj'=>8204,'zwj'=>8205,'lrm'=>8206,'rlm'=>8207, 
'ndash'=>8211,'mdash'=>8212,'lsquo'=>8216,'rsquo'=>8217,'sbquo'=>8218,'ldquo'=>8220, 
'rdquo'=>8221,'bdquo'=>8222,'dagger'=>8224,'Dagger'=>8225,'permil'=>8240,'lsaquo'=>8249, 
'rsaquo'=>8250,'euro'=>8364,'fnof'=>402,'Alpha'=>913,'Beta'=>914,'Gamma'=>915, 
'Delta'=>916,'Epsilon'=>917,'Zeta'=>918,'Eta'=>919,'Theta'=>920,'Iota'=>921, 
'Kappa'=>922,'Lambda'=>923,'Mu'=>924,'Nu'=>925,'Xi'=>926,'Omicron'=>927, 
'Pi'=>928,'Rho'=>929,'Sigma'=>931,'Tau'=>932,'Upsilon'=>933,'Phi'=>934, 
'Chi'=>935,'Psi'=>936,'Omega'=>937,'alpha'=>945,'beta'=>946,'gamma'=>947, 
'delta'=>948,'epsilon'=>949,'zeta'=>950,'eta'=>951,'theta'=>952,'iota'=>953, 
'kappa'=>954,'lambda'=>955,'mu'=>956,'nu'=>957,'xi'=>958,'omicron'=>959, 
'pi'=>960,'rho'=>961,'sigmaf'=>962,'sigma'=>963,'tau'=>964,'upsilon'=>965, 
'phi'=>966,'chi'=>967,'psi'=>968,'omega'=>969,'thetasym'=>977,'upsih'=>978, 
'piv'=>982,'bull'=>8226,'hellip'=>8230,'prime'=>8242,'Prime'=>8243,'oline'=>8254, 
'frasl'=>8260,'weierp'=>8472,'image'=>8465,'real'=>8476,'trade'=>8482,'alefsym'=>8501, 
'larr'=>8592,'uarr'=>8593,'rarr'=>8594,'darr'=>8595,'harr'=>8596,'crarr'=>8629, 
'lArr'=>8656,'uArr'=>8657,'rArr'=>8658,'dArr'=>8659,'hArr'=>8660,'forall'=>8704, 
'part'=>8706,'exist'=>8707,'empty'=>8709,'nabla'=>8711,'isin'=>8712,'notin'=>8713, 
'ni'=>8715,'prod'=>8719,'sum'=>8721,'minus'=>8722,'lowast'=>8727,'radic'=>8730, 
'prop'=>8733,'infin'=>8734,'ang'=>8736,'and'=>8743,'or'=>8744,'cap'=>8745, 
'cup'=>8746,'int'=>8747,'there4'=>8756,'sim'=>8764,'cong'=>8773,'asymp'=>8776, 
'ne'=>8800,'equiv'=>8801,'le'=>8804,'ge'=>8805,'sub'=>8834,'sup'=>8835, 
'nsub'=>8836,'sube'=>8838,'supe'=>8839,'oplus'=>8853,'otimes'=>8855,'perp'=>8869, 
'sdot'=>8901,'lceil'=>8968,'rceil'=>8969,'lfloor'=>8970,'rfloor'=>8971,'lang'=>9001, 
'rang'=>9002,'loz'=>9674,'spades'=>9824,'clubs'=>9827,'hearts'=>9829,'diams'=>9830, 
'nbsp'=>160,'iexcl'=>161,'cent'=>162,'pound'=>163,'curren'=>164,'yen'=>165, 
'brvbar'=>166,'sect'=>167,'uml'=>168,'copy'=>169,'ordf'=>170,'laquo'=>171, 
'not'=>172,'shy'=>173,'reg'=>174,'macr'=>175,'deg'=>176,'plusmn'=>177, 
'sup2'=>178,'sup3'=>179,'acute'=>180,'micro'=>181,'para'=>182,'middot'=>183, 
'cedil'=>184,'sup1'=>185,'ordm'=>186,'raquo'=>187,'frac14'=>188,'frac12'=>189, 
'frac34'=>190,'iquest'=>191,'Agrave'=>192,'Aacute'=>193,'Acirc'=>194,'Atilde'=>195, 
'Auml'=>196,'Aring'=>197,'AElig'=>198,'Ccedil'=>199,'Egrave'=>200,'Eacute'=>201, 
'Ecirc'=>202,'Euml'=>203,'Igrave'=>204,'Iacute'=>205,'Icirc'=>206,'Iuml'=>207, 
'ETH'=>208,'Ntilde'=>209,'Ograve'=>210,'Oacute'=>211,'Ocirc'=>212,'Otilde'=>213, 
'Ouml'=>214,'times'=>215,'Oslash'=>216,'Ugrave'=>217,'Uacute'=>218,'Ucirc'=>219, 
'Uuml'=>220,'Yacute'=>221,'THORN'=>222,'szlig'=>223,'agrave'=>224,'aacute'=>225, 
'acirc'=>226,'atilde'=>227,'auml'=>228,'aring'=>229,'aelig'=>230,'ccedil'=>231, 
'egrave'=>232,'eacute'=>233,'ecirc'=>234,'euml'=>235,'igrave'=>236,'iacute'=>237, 
'icirc'=>238,'iuml'=>239,'eth'=>240,'ntilde'=>241,'ograve'=>242,'oacute'=>243, 
'ocirc'=>244,'otilde'=>245,'ouml'=>246,'divide'=>247,'oslash'=>248,'ugrave'=>249, 
'uacute'=>250,'ucirc'=>251,'uuml'=>252,'yacute'=>253,'thorn'=>254,'yuml'=>255 
) as $alpha=>$num) 
$news=str_replace("&$alpha;", "&#$num;", $news); 

您可以preg_replacearray_map做票友的事情,但是這是你需要的數據。或者,如果性能對您而言是個問題,您可以做一些奇特的多字節字符檢測並完全繞過命名的實體步驟。 PHP網站上有很多例子。

嚴格地說,如果你已經打上你的XML文檔被utf-8編碼,你可以離開實體完全編碼出來,只是編碼四個主要球員:

$table = array('&' => '&amp;', '<' => '&lt;', '>' => '&gt;', '"' => '&quot;'); 
$news = str_replace(array_keys($table), array_values($table), $_POST["news"]); 

ñ。