read - write xml c#
El análisis de la cadena xml en un documento xml falla si la cadena comienza con la sección<? Xml…?> (5)
Tengo un archivo XML que comienza así:
<?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 el siguiente código:
byte[] fileContent = //gets bytes
string stringContent = Encoding.UTF8.GetString(fileContent);
XDocument xml = XDocument.Parse(stringContent);
Me sale la siguiente XmlException:
Los datos a nivel de la raíz no es válida. Línea 1, posición 1.
Cortar la versión y codificar el nodo soluciona el problema. ¿Por qué? ¿Cómo procesar este xml correctamente?
¿Por qué molestarse en leer el archivo como una secuencia de bytes y luego convertirlo en una cadena mientras es un archivo xml? Simplemente deje el marco de trabajo, haga la carga por usted y haga frente a las codificaciones:
var xml = XDocument.Load("test.xml");
¿Tiene una byte-order-mark (BOM) al principio de su XML y coincide con su codificación? Si corta el encabezado, también eliminará la lista de materiales y, si eso es incorrecto, es posible que el análisis posterior funcione.
Es posible que deba inspeccionar su documento a nivel de bytes para ver la lista de materiales.
Mi primer pensamiento fue que la codificación es Unicode al analizar XML desde 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 la marca de orden de preámbulo / byte (BOM) de UTF8, que es una firma de tres bytes opcionalmente presente al inicio de una secuencia UTF-8. Estos tres bytes son una sugerencia en cuanto a la codificación que se utiliza en la secuencia.
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
, así que simplemente cargue su XDocument
desde un XmlTextReader
:
XDocument xml;
using (var xmlStream = new MemoryStream(fileContent))
using (var xmlReader = new XmlTextReader(xmlStream))
{
xml = XDocument.Load(xmlReader);
}
Prueba esto:
int startIndex = xmlString.IndexOf(''<'');
if (startIndex > 0)
{
xmlString = xmlString.Remove(0, startIndex);
}
Si solo tiene bytes, puede cargar los bytes en una secuencia:
XmlDocument oXML;
using (MemoryStream oStream = new MemoryStream(oBytes))
{
oXML = new XmlDocument();
oXML.Load(oStream);
}
O puede convertir los bytes en una cadena (suponiendo que conoce la codificación) antes de cargar el XML:
string sXml;
XmlDocument oXml;
sXml = Encoding.UTF8.GetString(oBytes);
oXml = new XmlDocument();
oXml.LoadXml(sXml);
He mostrado mi ejemplo como compatible con .NET 2.0, si estás usando .NET 3.5 puedes usar XDocument
lugar de XmlDocument
.
Cargue los bytes en una secuencia:
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);