2010-01-21 22 views
23

Tengo un archivo XML begining así:cadena de análisis XML a un documento XML falla si la cadena comienza con <?xml... ?> sección

<?xml version="1.0" encoding="utf-8"?> 
<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition"> 
    <DataSources> 

cuando corro siguiente código:

byte[] fileContent = //gets bytes 
      string stringContent = Encoding.UTF8.GetString(fileContent); 
      XDocument xml = XDocument.Parse(stringContent); 

consigo siguiente XmlException:

Los datos en el nivel raíz no son válidos. Línea 1, posición 1.

Al cortar la versión y el nodo de codificación se soluciona el problema. ¿Por qué? Cómo procesar este xml correctamente?

Respuesta

16

Si sólo dispone de bytes que bien podría cargar los bytes en una corriente :

XmlDocument oXML; 

using (MemoryStream oStream = new MemoryStream(oBytes)) 
{ 
    oXML = new XmlDocument(); 
    oXML.Load(oStream); 
} 

O podría convertir los bytes en una cadena (suponiendo que conoce la codificación) sea primer plano de cargar el XML:

string sXml; 
XmlDocument oXml; 

sXml = Encoding.UTF8.GetString(oBytes); 
oXml = new XmlDocument(); 
oXml.LoadXml(sXml); 

he mostrado mi ejemplo como .NET 2.0 compatible, si está utilizando .NET 3.5 se puede utilizar en lugar de XDocumentXmlDocument.

Cargar los bytes en una corriente:

XDocument oXML; 

using (MemoryStream oStream = new MemoryStream(oBytes)) 
using (XmlTextReader oReader = new XmlTextReader(oStream)) 
{ 
    oXML = XDocument.Load(oReader); 
} 

convertir los bytes en una cadena:

string sXml; 
XDocument oXml; 

sXml = Encoding.UTF8.GetString(oBytes); 
oXml = XDocument.Parse(sXml); 
+0

el problema es que necesito usar XDocument – agnieszka

+0

@agnieszka - He actualizado mi respuesta para guiarlo a través del uso de XDocument. – stevehipwell

+0

terminé haciendo esto en realidad;) gracias de todos modos – agnieszka

6

¿Tiene un byte-order-mark (BOM) al principio de su XML, y coincide con su codificación? Si corta su encabezado, también cortará la lista de materiales y, si eso es incorrecto, el siguiente análisis puede funcionar.

Es posible que tenga que inspeccionar su documento en el nivel de bytes para ver la lista de materiales.

+0

lo que es un orden de bytes-marca. ..? y ¿cómo puedo averiguar la codificación del documento? Solo sospecho que es utf-8 (leer el texto es legible) – agnieszka

+0

Ver el enlace que publiqué. Es una secuencia de bytes * antes * del encabezado que actúa como una directiva para la codificación del documento. –

9

¿Por qué molestarse en leer el archivo como una secuencia de bytes y luego convertirlo en una cadena mientras es un archivo xml? Acaba de salir del marco do la carga para usted y hacer frente a las codificaciones:

var xml = XDocument.Load("test.xml"); 
+1

Porque no obtengo el xml de una ruta. Solo tengo contenido de bytes – agnieszka

+0

¿Y de dónde vienen esos bytes? Base de datos, flujo de red, ...? –

+0

Lista en un Sharepoint. Se llama item.File.OpenBinary() – agnieszka

17

Mi primer pensamiento fue que la codificación es Unicode al analizar XML a partir de un tipo de cadena .NET. Parece, sin embargo, que el análisis de XDocument es bastante indulgente con respecto a esto.

El problema está realmente relacionado con el preámbulo UTF8/marca de orden de bytes (BOM), que es una firma de tres bytes optionally present al comienzo de una secuencia UTF-8. Estos tres bytes son una pista sobre la codificación que se usa en la transmisión.

Puede determinar el preámbulo de una codificación llamando al método GetPreamble en una instancia de la clase System.Text.Encoding. Por ejemplo:

// returns { 0xEF, 0xBB, 0xBF } 
byte[] preamble = Encoding.UTF8.GetPreamble(); 

El preámbulo debe ser manejado correctamente por XmlTextReader, por lo que simplemente cargar su XDocument de un XmlTextReader:

XDocument xml; 
using (var xmlStream = new MemoryStream(fileContent)) 
using (var xmlReader = new XmlTextReader(xmlStream)) 
{ 
    xml = XDocument.Load(xmlReader); 
} 
+0

Tenga en cuenta que UTF-8 'pre-amble' es una invención de Microsoft que no está respaldada por ningún estándar Unicode, a diferencia de las listas de materiales normales UTF-16. Nunca se debe usar para escribir, aunque tendrás que manejarlo al leer, ya que a menudo te encontrarás con el molesto blighter en la naturaleza. – bobince

+0

@bobince - Acepto (aunque está permitido por el estándar Unicode, pero se desaconseja su uso; consulte la página 36 de http://www.unicode.org/versions/Unicode5.0.0/ch02.pdf#G19273 para obtener más información). información). –

+0

bien, pero ¿cómo procesar este xml correctamente? – agnieszka

2

Prueba esto:

int startIndex = xmlString.IndexOf('<'); 
if (startIndex > 0) 
{ 
    xmlString = xmlString.Remove(0, startIndex); 
} 
+2

Ayudaría si explicara que esto fue omitir por la fuerza el preámbulo/BOM. – binki

Cuestiones relacionadas