2012-07-03 11 views
50

वेबसर्वर utf-8 एन्कोडिंग के साथ प्रतिक्रियाओं प्रस्तुत कर रहा है सभी फाइलों को UTF-8 एन्कोडिंग के साथ सहेजे जाते संभाल करने में नाकाम रहने के लिए, और सब कुछ मैं सेटिंग के बारे में पता UTF-8 एन्कोडिंग के लिए स्थापित किया गया है ।पीएचपी DOMDocument utf-8 वर्णों (☆)

यहां एक त्वरित कार्यक्रम यदि उत्पादन में काम करता है परीक्षण करने के लिए दिया गया है:

<?php 
$html = <<<HTML 
<!doctype html> 
<html> 
<head> 
    <meta charset="utf-8"> 
    <title>Test!</title> 
</head> 
<body> 
    <h1>☆ Hello ☆ World ☆</h1> 
</body> 
</html> 
HTML; 

$dom = new DomDocument("1.0", "utf-8"); 
$dom->loadHTML($html); 

header("Content-Type: text/html; charset=utf-8"); 
echo($dom->saveHTML()); 

कार्यक्रम का उत्पादन होता है:

<!DOCTYPE html> 
<html><head><meta charset="utf-8"><title>Test!</title></head><body> 
    <h1>&acirc;&#152;&#134; Hello &acirc;&#152;&#134; World &acirc;&#152;&#134;</h1> 
</body></html> 

कौन सा renders के रूप में:

एक ~ † हैलो â ~ † विश्व â~ †


मैं गलत क्या कर सकता था? Utf-8 को ठीक से संभालने के लिए DomDocument को बताने के लिए मुझे कितना विशिष्ट होना चाहिए?

+0

सवाल को लाने के लिए धन्यवाद, एक ऐसी ही एक है: यहाँ एक नमूना कोड [चीनी या अन्य विदेशी भाषा रखने के लिए कैसे के रूप में वे उन्हें कोड में परिवर्तित करने के बजाय कर रहे हैं?] (Http: // stackoverflow .com/q/10237238/367456) हालांकि आप एक हैक पर विचार कर सकते हैं। – hakre

+0

संबंधित: [PHP अनुरोध # 47875 - एचटीएमएल इनपुट एन्कोडिंग सेट करने के लिए कोई विकल्प नहीं] (https://bugs.php.net/bug.php?id=47875) – hakre

+1

आश्चर्यजनक रूप से पर्याप्त: PHP-दस्तावेज़ कहता है: 'डीओएम एक्सटेंशन यूटीएफ -8 एन्कोडिंग का उपयोग करता है। आईएसओ -885 9 -1 एन्कोडिंग या अन्य एन्कोडिंग के लिए आईकॉनवी में ग्रंथों के साथ काम करने के लिए utf8_encode() और utf8_decode() का उपयोग करें। देखें: http://www.php.net/manual/en/intro.dom.php – jens

उत्तर

107

DOMDocument::loadHTML() एक HTML स्ट्रिंग की उम्मीद है। प्रति यह चश्मा है

HTML को डिफ़ॉल्ट रूप ISO-8859-1 एन्कोडिंग (आईएसओ लैटिन वर्णमाला नंबर 1) का उपयोग करता है। यह अब से लंबा है, 6.1. The HTML Document Character Set देखें। हकीकत में यह सामान्य वेबब्रोसर में Windows-1252 के लिए डिफ़ॉल्ट समर्थन है।

मैं अब तक वापस जाता हूं क्योंकि PHP का DOMDocument libxml पर आधारित है और यह HTMLparser लाता है जो HTML 4.0 के लिए डिज़ाइन किया गया है।

मैं कहूंगा कि यह मानना ​​सुरक्षित है कि आप ISO-8859-1 एन्कोडेड स्ट्रिंग लोड कर सकते हैं।

आपकी स्ट्रिंग UTF-8 एन्कोडेड है। सभी पात्रों को 127/h7F से HTML Entities में बदलें और आप ठीक हैं। आपको लगता है कि अपनी खुद की नहीं करना चाहते हैं, कि क्या mb_convert_encodingHTML-ENTITIES लक्ष्य एन्कोडिंग के साथ करता है:

  • उन अक्षर हैं जो संस्थाओं नामित किया है, नामित entitiy मिल जाएगा। € -> &euro;
  • दूसरों को उनकी संख्यात्मक (दशमलव) इकाई मिलती है, उदा।

    $html = preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function($match) { 
        list($utf8) = $match; 
        $entity = mb_convert_encoding($utf8, 'HTML-ENTITIES', 'UTF-8'); 
        printf("%s -> %s\n", $utf8, $entity); 
        return $entity; 
    }, $html); 
    

    अपने स्ट्रिंग के लिए यह अनुकरणीय आउटपुट: ☆ -> &#9734;

निम्नलिखित है कि एक कॉलबैक फ़ंक्शन का उपयोग करके प्रगति में थोड़ा और अधिक से दिखाई दे रही एक कोड उदाहरण है

☆ -> &#9734; 
☆ -> &#9734; 
☆ -> &#9734; 

वैसे भी, यह सिर्फ आपकी स्ट्रिंग में गहरी लग रही है। आप इसे या तो एन्कोडिंग loadHTML में परिवर्तित करना चाहते हैं। यही कारण है कि एचटीएमएल संस्थाओं में US-ASCII के सभी बाहर परिवर्तित करके किया जा सकता है:

$us_ascii = mb_convert_encoding($utf_8, 'HTML-ENTITIES', 'UTF-8'); 

लें देखभाल कि आपके इनपुट वास्तव में UTF-8 एन्कोडेड है।यदि आपके पास मिश्रित एन्कोडिंग भी हैं (जो कुछ इनपुट के साथ हो सकती हैं) mb_convert_encoding प्रति स्ट्रिंग केवल एक एन्कोडिंग को संभाल सकता है। मैंने पहले से ही रेखांकित किया है कि नियमित रूप से अभिव्यक्तियों की सहायता से स्ट्रिंग प्रतिस्थापन कैसे करें, इसलिए मैं अब और विवरण छोड़ देता हूं।

अन्य विकल्प संकेत एन्कोडिंग है। यह दस्तावेज़ को संशोधित करके और

<meta http-equiv="content-type" content="text/html; charset=utf-8"> 

जो एक सामग्री-प्रकार है जो एक वर्णमाला निर्दिष्ट करता है जोड़कर किया जा सकता है। एचटीएमएल स्ट्रिंग्स के लिए यह भी सबसे अच्छा अभ्यास है जो वेबसर्वर के माध्यम से उपलब्ध नहीं है (उदा। डिस्क पर सहेजा गया है या आपके उदाहरण में स्ट्रिंग के अंदर)। वेबसर्वर आमतौर पर सेट हेडर के रूप में सेट करता है।

$dom = new DomDocument(); 
$dom->loadHTML('<meta http-equiv="content-type" content="text/html; charset=utf-8">'.$html); 

एचटीएमएल प्रति 2.0 चश्मा, तत्वों है कि केवल एक दस्तावेज़ के <head> अनुभाग में दिखाई कर सकते हैं:

आप गलत चेतावनी की परवाह नहीं करते हैं, तो आप बस इसे स्ट्रिंग के सामने जोड़ सकते हैं , स्वचालित रूप से वहां रखा जाएगा। यह भी यहां होता है। निर्गम (सुंदर प्रिंट):

<!DOCTYPE html> 
<html> 
    <head> 
    <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
    <meta charset="utf-8"> 
    <title>Test!</title> 
    </head> 
    <body> 
    <h1>☆ Hello ☆ World ☆</h1>  
    </body> 
</html> 
+2

@ hakre: वह सही था! आपने मेरी गंभीर समस्या हल की है और अब मुझे कोई सिरदर्द नहीं है !! – Aliweb

+1

+1 ग्रेट उत्तर, लेकिन आप किस विधि की सिफारिश करते हैं - 'mb_convert_encoding()' या 'loadHTML()' में मेटा टैग को प्रीपेड करते हुए? – Nate

+1

@Nate: मैं कहूंगा कि यह निर्भर करता है। मैं आमतौर पर 'mb_convert_encoding() 'की अनुशंसा नहीं करता हूं लेकिन इस मामले के लिए मैं किसी भी तरह से करता हूं। हालांकि यह व्यक्तिगत वरीयता का विवरण है। और यह अभी भी निर्भर करता है कि आप अपने स्वयं के चरण में रूपांतरण करना चाहते हैं या आप इसे 'DOOMDocument :: loadHTML()' में तोड़ना चाहते हैं जो दस्तावेज़ में मेटा तत्व को लीक करता है। मैं उदाहरण के लिए नहीं जानता कि क्या होगा यदि वह तत्व पहले से मौजूद है। मैंने कभी भी एक बचत बिंदु पर इसका परीक्षण नहीं किया है, लेकिन यह आमतौर पर "बस काम करता है" (टीएम)। उत्तर में विभिन्न तरीके स्पष्टीकरण के लिए अधिक हैं। वैकल्पिक विधि का उपयोग करने वाले किसी भी व्यक्ति के लिए – hakre

12
<?php 
    header("Content-type: text/html; charset=utf-8"); 
    $html = <<<HTML 
<!doctype html> 
<html> 
<head> 
    <meta charset="utf-8"> 
    <title>Test!</title> 
</head> 
<body> 
    <h1>☆ Hello ☆ World ☆</h1> 
</body> 
</html> 
HTML; 

    $html = mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8"); 
    $dom = new DomDocument("1.0", "utf-8"); 
    $dom->loadHTML($html); 

    header("Content-Type: text/html; charset=utf-8"); 
    echo($dom->saveHTML()); 

आउटपुट:

<!DOCTYPE html> 
<html><head><meta charset="utf-8"><title>Test!</title></head><body> 
    <h1>&#9734; Hello &#9734; World &#9734;</h1> 
</body></html> 
+1

@powtac: इन संस्करणों को वास्तव में उस 'हेडर' लाइन की आवश्यकता नहीं है। हमारे सभी पात्रों का हिस्सा नहीं है- ascii यहां इकाइयां हैं। धरती पर कोई भी ब्राउज़र हमेशा इसे तब तक प्रदर्शित करेगा जब तक आप हमें (गलत) एन्कोडिंग निर्दिष्ट नहीं करते- हमें साझा नहीं करते हैं। लेकिन सिर्फ ध्यान देना, यह गलत नहीं है। – hakre

15

वहाँ उस के लिए एक तेजी से ठीक है, DOMDocument में अपने HTML दस्तावेज़ लोड करने के बाद, तो आप सिर्फ सेट (या बेहतर रीसेट कहा) मूल एन्कोडिंग।

$dom = new DOMDocument(); 
$dom->loadHTML('<?xml encoding="UTF-8">' . $html); 

foreach ($dom->childNodes as $item) 
    if ($item->nodeType == XML_PI_NODE) 
     $dom->removeChild($item); 
$dom->encoding = 'UTF-8'; // reset original encoding 
+0

से कक्षाओं को नहीं हटाता है, यह मेटा टैग जोड़ने के हैकर के संस्करण से बेहतर काम करता है क्योंकि मेटा से मेटा हटाए गए वर्ग जोड़ना टैग –

+4

हम्म, यह उत्तर एक डीजे-वीयू की तरह है - http://stackoverflow.com/a/10834989/367456 – hakre

+0

हम्म, हो सकता है ..मेरे पास उपयोगी tippets के गुच्छा के साथ एक txt में कोड था। मैं दावा नहीं करता कि यह कुछ मूल सामान है, भले ही यह DOMDocument क्लास का कुछ मानक उपयोग है। – DeZeA

संबंधित मुद्दे