2011-01-04 18 views
5

Sto utilizzando l'API di Google Meteo per un widget.Errore di analisi xml: "Carattere non valido"

Tutto è bene e dandy, tranne che oggi ho incontrato un problema che non riesco a risolvere. Quando chiamato con questa posizione:

http://www.google.com/ig/api?weather=dunjkovec,medimurska,croatia&hl=en

ottengo questo errore:

XML parse error 9 'Invalid character' at line 1, column 169 (byte index 199) 

Ho il sospetto che il problema è qui: Nedelišće

Il blocco di codice è questo:

$parser = xml_parser_create('UTF-8'); 
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
$ok = xml_parse_into_struct($parser, $data, $values); 
if (!$ok) { 
    $errmsg = sprintf("XML parse error %d '%s' at line %d, column %d (byte index %d)", 
    xml_get_error_code($parser), 
    xml_error_string(xml_get_error_code($parser)), 
    xml_get_current_line_number($parser), 
    xml_get_current_column_number($parser), 
    xml_get_current_byte_index($parser)); 
} 

$ dati è l'aria la tenda dei valori xml e $ è vuota.

Qualcuno può aiutarmi? Grazie mille!

EDIT ----------------------------------

Dopo aver letto il post di Hussein ho scoperto che il problema è nel modo in cui il file viene recuperato.

ho cercato file_get_contents e cURL. Entrambi i rendimenti:

che è la linea che crea problemi. O così ho pensato! Ho provato questo html_entity_decode ($ data, ENT_NOQUOTES, 'UTF-8') e non funzionava, quindi ho fatto una scoperta, non posso echo il contenuto dell'xml, posso solo stamparli e vedere i risultati in la fonte html! Con qualsiasi altra posizione nel mondo funziona, solo questo crea problemi ... Voglio piangere :-(

EDIT 2 -------------------- ------------

Per qualcuno che si preoccupa ho fissato il problema con queste linee di codice dopo il recupero del file XML dal api:.

$data = mb_convert_encoding($data, 'UTF-8', mb_detect_encoding($data, 'UTF-8, ISO-8859-1', true)); 
$data = html_entity_decode($data,ENT_NOQUOTES,'UTF-8'); 

poi analizzare il codice XML , ha funzionato come un fascino Ho segnato la risposta di hussein perché mi ha messo sulla strada giusta

+0

Qual è la tua versione di PHP? – Tomalak

+0

La versione PHP potrebbe essere un problema con la codifica. Google identifica correttamente l'XML come UTF-8 nell'intestazione, ma non nella dichiarazione XML. Come stai recuperando e memorizzando l'XML prima di caricarlo? A seconda della configurazione dell'ambiente, suppongo sia possibile che sia stato convertito implicitamente in ISO-8859-1 a un certo punto, il che causerebbe l'errore di carattere non valido quando è caricato. –

+1

Congratulazioni! È una soluzione ancora migliore .. Grazie per aver condiviso :) – eHussain

risposta

4

Dopo aver letto il tuo problema, I t ho trovato la stessa cosa sulla mia macchina. Quello che ho fatto è 1. File xml scaricato sul mio computer locale dall'URL che hai postato. 2. Utilizzato lo script di analisi xml per preparare la struttura da XML.

Sorprendentemente ha funzionato perfettamente sulla mia macchina, anche se XML ha Nedelišće parola chiave. Quindi, vedo il problema nel modo di leggere il file XML.

Sarebbe facile per eseguire il debug se mi può dire il modo in cui si sta leggendo l'API modulo XML di Google. Stai usando CURL?

MODIFICA --------------------------------------------- -

Hi 0plus1,

ho preparato una funzione di supporto per convertire questi caratteri speciali in hTML per rendendolo in grado per l'analisi ..

Sto incollando l'intero codice qui. Utilizzare script seguente ..

function utf8tohtml($utf8, $encodeTags) 
{ 
    $result = ''; 
    for ($i = 0; $i < strlen($utf8); $i++) 
    { 
     $char = $utf8[$i]; 
     $ascii = ord($char); 
     if ($ascii < 128) 
     { 
      // one-byte character 
      $result .= ($encodeTags) ? htmlentities($char , ENT_QUOTES, 'UTF-8') : $char; 
     } else if ($ascii < 192) 
     { 
      // non-utf8 character or not a start byte 
     } else if ($ascii < 224) 
     { 
      // two-byte character 
      $result .= htmlentities(substr($utf8, $i, 2), ENT_QUOTES, 'UTF-8'); 
      $i++; 
     } else if ($ascii < 240) 
     { 
      // three-byte character 
      $ascii1 = ord($utf8[$i+1]); 
      $ascii2 = ord($utf8[$i+2]); 
      $unicode = (15 & $ascii) * 4096 + 
       (63 & $ascii1) * 64 + 
       (63 & $ascii2); 
      $result .= "&#$unicode;"; 
      $i += 2; 
     } else if ($ascii < 248) 
     { 
      // four-byte character 
      $ascii1 = ord($utf8[$i+1]); 
      $ascii2 = ord($utf8[$i+2]); 
      $ascii3 = ord($utf8[$i+3]); 
      $unicode = (15 & $ascii) * 262144 + 
       (63 & $ascii1) * 4096 + 
       (63 & $ascii2) * 64 + 
       (63 & $ascii3); 
      $result .= "&#$unicode;"; 
      $i += 3; 
     } 
    } 
    return $result; 
} 


$curlHandle = curl_init(); 
$serviceUrl = "http://www.google.com/ig/api?weather=dunjkovec,medimurska,croatia&hl=en"; 
// setup the basic options for the curl 
curl_setopt($curlHandle , CURLOPT_URL, $serviceUrl); 
curl_setopt($curlHandle , CURLOPT_HEADER , 0); 
curl_setopt($curlHandle , CURLOPT_HTTPHEADER , array("Cache-Control: no-cache","Content-type: application/x-www-form-urlencoded;charset=UTF-8")); 
curl_setopt($curlHandle , CURLOPT_FOLLOWLOCATION , true); 
curl_setopt($curlHandle , CURLOPT_RETURNTRANSFER , true); 
curl_setopt($curlHandle , CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'); 
$data = curl_exec($curlHandle); 
// echo $data; 
$data = utf8tohtml($data , false); 
echo $data; 

$parser = xml_parser_create("UTF-8"); 
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); 
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
$ok = xml_parse_into_struct($parser, $data, $values); 
if (!$ok) { 
    $errmsg = sprintf("XML parse error %d '%s' at line %d, column %d (byte index %d)", 
    xml_get_error_code($parser), 
    xml_error_string(xml_get_error_code($parser)), 
    xml_get_current_line_number($parser), 
    xml_get_current_column_number($parser), 
    xml_get_current_byte_index($parser)); 
} 
echo "<pre>"; 
print_r($values); 
echo "</pre>"; 

Spero che questo vi aiuterà.

Grazie!

Hussain.

+0

Ho provato sia con cURL che con file_get_contents. Entrambi gli stessi risultati ... – 0plus1

+0

Ho approfondito il problema dopo aver letto il tuo post, questo è quello che ottengo Penso che il problema sia qui! – 0plus1

+0

Ha funzionato per me con problemi simili all'OP. – sparrow

0

Ancora, quale versione di php stai usando? xml_parser_create accetta la codifica come parametro, ma solo per l'output, non in alcune versioni. http://www.php.net/manual/en/function.xml-parser-create.php

Si consiglia di prendere in considerazione la creazione di una stringa utf-8 vuota e quindi di riempirla con l'XML recuperato da Google o di convertire esplicitamente la stringa in UTF-8.

string utf8_encode (string $data) 

Google sia correttamente informandoci dei dati è UTF-8, ma solo nell'intestazione, non in XML vero e proprio.

1

Nella risposta viene specificato il numero da codificare con ISO 8859-1 (vedere response on Web-Sniffer.net) e non in UTF-8 nella Content-Type header field. Quindi, specificare ISO-8859-1 come codifica o omettere tale parametro e xml_parser_create tenta di identificare la codifica.

+0

Interessante, Firefox mi stava dicendo che era UTF-8. Penso che con quei personaggi avrà comunque bisogno dell'UTF-8. –

+0

@James Walford: Hm, penso che la codifica del contenuto dipenda dall'agente utente. Se usi 'Mozilla/5.0' nella richiesta, otterrai UTF-8. – Gumbo

+0

quindi forse l'impostazione dell'intestazione della richiesta Accept-Charset su UTF-8 quando si chiama google potrebbe essere d'aiuto? –

Problemi correlati