Pregunta

Para cargar archivos XML con codificación arbitraria tengo el siguiente código:

Encoding encoding;
using (var reader = new XmlTextReader(filepath))
{
    reader.MoveToContent();
encoding = reader.Encoding;
}

var settings = new XmlReaderSettings { NameTable = new NameTable() };
var xmlns = new XmlNamespaceManager(settings.NameTable);
var context = new XmlParserContext(null, xmlns, "", XmlSpace.Default, 
    encoding);
using (var reader = XmlReader.Create(filepath, settings, context))
{
    return XElement.Load(reader);
}

Esto funciona, pero parece un poco ineficiente abrir el archivo dos veces. ¿Hay una mejor manera de detectar la codificación de modo que pueda hacer:

 1. Open file
 2. Detect encoding
 3. Read XML into an XElement
 4. Close file
¿Fue útil?

Solución

Ok, debería haber pensado en esto antes. Tanto XmlTextReader (que nos proporciona la codificación) como XmlReader.Create (que nos permite especificar la codificación) aceptan una secuencia. Entonces, ¿qué hay de abrir primero un FileStream y luego usar esto con XmlTextReader y XmlReader, de esta manera:

using (var txtreader = new FileStream(filepath, FileMode.Open))
{
    using (var xmlreader = new XmlTextReader(txtreader))
    {
        // Read in the encoding info
        xmlreader.MoveToContent();
        var encoding = xmlreader.Encoding;

        // Rewind to the beginning
        txtreader.Seek(0, SeekOrigin.Begin);

        var settings = new XmlReaderSettings { NameTable = new NameTable() };
        var xmlns = new XmlNamespaceManager(settings.NameTable);
        var context = new XmlParserContext(null, xmlns, "", XmlSpace.Default,
                 encoding);

        using (var reader = XmlReader.Create(txtreader, settings, context))
        {
            return XElement.Load(reader);
        }
    }
}

Esto funciona como un encanto. La lectura de archivos XML de una manera independiente de codificación debería haber sido más elegante, pero al menos me saldré con solo un archivo abierto.

Otros consejos

Otra opción, bastante simple, es usar Linq to XML. El método Load lee automáticamente la codificación del archivo xml. Luego puede obtener el valor del codificador utilizando XDeclaration . Codificación de propiedad . Un ejemplo de MSDN:

// Create the document
XDocument encodedDoc16 = new XDocument(
new XDeclaration("1.0", "utf-16", "yes"),
new XElement("Root", "Content")
);
encodedDoc16.Save("EncodedUtf16.xml");
Console.WriteLine("Encoding is:{0}", encodedDoc16.Declaration.Encoding);
Console.WriteLine();

// Read the document
XDocument newDoc16 = XDocument.Load("EncodedUtf16.xml");
Console.WriteLine("Encoded document:");
Console.WriteLine(File.ReadAllText("EncodedUtf16.xml"));
Console.WriteLine();
Console.WriteLine("Encoding of loaded document is:{0}", newDoc16.Declaration.Encoding);

Si bien es posible que esto no sirva el póster original, ya que tendría que refactorizar mucho código, es útil para alguien que tenga que escribir un código nuevo para su proyecto, o si cree que vale la pena refactorizarlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top