2011-09-21 20 views
8

Al responder this question, me encontré con una situación que no entiendo. El PO estaba tratando de cargar XML de la siguiente ubicación: http://www.google.com/ig/api?weather=12414&hl=itXmlDocument.Load falla, LoadXml funciona:

La solución obvia es:

string m_strFilePath = "http://www.google.com/ig/api?weather=12414&hl=it"; 
XmlDocument myXmlDocument = new XmlDocument(); 
myXmlDocument.Load(m_strFilePath); //Load NOT LoadXml 

Sin embargo esto no funciona con

XmlException: Carácter no válido en la codificación dada. Línea 1, posición 499.

Parece que se asfixia en el à de Umidità.

otoh, las siguientes obras excelentes:

var m_strFilePath = "http://www.google.com/ig/api?weather=12414&hl=it"; 
string xmlStr; 
using(var wc = new WebClient()) 
{ 
    xmlStr = wc.DownloadString(m_strFilePath); 
} 
var xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml(xmlStr); 

estoy desconcertado por esto. ¿Alguien puede explicar por qué la primera falla, pero la última funciona bien?

Cabe destacar que la declaración xml del documento omite una codificación.

+0

¿Es posible que WebClient htmlencodes? – Nicolai

Respuesta

12

El WebClient utiliza la información de codificación en las cabeceras de la respuesta HTTP para determinar la codificación correcta (en este caso ISO-8859-1 que se basa ASCII, es decir, 8 bits por carácter)

Parece que XmlDocument.Load no utiliza esta información y como la codificación también falta en la declaración xml, tiene que adivinar una codificación y se equivoca. Algunas búsquedas me llevan a creer que elige UTF-8.

Si queremos ser realmente técnicos, el carácter que arroja es "à", que es 0xE0 en la codificación ISO-8859-1, pero este no es un carácter válido en UTF-8 - específicamente la representación binaria de este personaje es:

11100000 

Si usted tiene una excavación alrededor de la UTF-8 Wikipedia article podemos ver que esto indica un punto de código (es decir, caracteres) que consta de un total de 3 bytes que tienen el siguiente formato:

Byte 1  Byte 2  Byte 3 
----------- ----------- ----------- 
1110xxxx 10xxxxxx 10xxxxxx 

Pero si tenemos un mira hacia atrás en el documento los siguientes dos caracteres son ":" que es 0x3A y 0x20 en ISO-8859-1. Esto significa que lo que en realidad terminan con es:

Byte 1  Byte 2  Byte 3 
----------- ----------- ----------- 
11100000 00111010 00100000 

Ni la 2ª o 3ª bytes de la secuencia tienen 10 como los dos bits más significativos (lo que indicaría una continuación), por lo que este personaje no tiene sentido en UTF-8.

+0

Apertura de reflector ahora ... – spender

+0

Al observar el código, parece que Load crea una instancia de 'XmlTextReader' pero no intenta establecer una codificación. – spender

+0

@spender Sí, eché un vistazo en el interior de ILSpy, pero fue difícil ver exactamente qué estaba sucediendo. ¡Interesante pregunta, disfruté respondiendo este!:-) – Justin

2

Cadena Umidità como nodo El texto debe estar dentro de <! [CDATA [Umidità]]> esto no dará ningún error en XmlDocument.Load.

+0

Esta pregunta no se trata de cómo corregir el XML, sino de por qué el comportamiento es diferente entre los dos métodos descritos en mi pregunta anterior. – spender

+1

En realidad, las etiquetas CDATA indican datos de caracteres al analizador para que las construcciones XML (como "<") no tengan que escaparse, pero en este caso es un problema de codificación, el uso de etiquetas CDATA no habría hecho ninguna diferencia aquí. – Justin

Cuestiones relacionadas