Q:

XmlDocument Exception: valor hexadecimal 0x1a, é um caractere inválido

Tenho um projeto que lê um XML gerado por outro programa na qual eu não tenho acesso ao código fonte. O problema é que o XML gerado vem com um caractere especial no final, e quando vou tentar ler o XML a exception é lançada.
Segue o código:
XmlDocument xmlDoc = new XmlDocument();
try
{
   xmlDoc.Load(localMontaXML);
}
catch (Exception ex)
{
   erros.Add(ex.Message);
}
ErrorChecker.Check(erros);

Têm alguma forma de ignorar esse caractere?
Utilizo Windows Forms com .Net 3.5

A:

Tem sim cara, mas antes você deve considerar a possibilidade de o arquivo estar vindo corrompido ou algo do tipo. Se você tem certeza que este arquivo está íntegro, e que apenas existe um caractere inválido no final por alguma razão desconhecida (?), você pode jogar o arquivo em memória exceto o último caractere, obtendo o seu xml válido. 
Existem duas formas que eu conheço de fazer isso. Observe o código a seguir:
METODO 1
using (MemoryStream ms = new MemoryStream()) // cria um stream de memória
using (var fs = new FileStream(@"C:\sample.xml", FileMode.Open, FileAccess.Read))
// abre o arquivo xml. No caso C:\sample.xml
{
    byte[] bytes = new byte[fs.Length]; // onde ficará o conteúdo do arquivo - 1
    fs.Read(bytes, 0, (int)fs.Length); // lê o arquivo
    ms.Write(bytes, 0, (int)fs.Length-1); // escreve tudo exceto o último byte (length - 1)

    ms.Seek(0, SeekOrigin.Begin); // volta para o início do stream

    XDocument doc = XDocument.Load(ms); // carrega o arquivo em memória
    Console.WriteLine(doc.Root.Value); // teste de leitura
}

METODO 2
using (var fs = new FileStream(@"C:\sample.xml", FileMode.Open, FileAccess.Read))
// cria um arquivo mapeado em memória a partir do seu FileStream
using (var mmf = MemoryMappedFile.CreateFromFile(fs,"xml",fs.Length,MemoryMappedFileAccess.Read,null,System.IO.HandleInheritability.None,true)) 
{
    // cria um stream que enxerga até o final do arquivo - 1
    using (var str = mmf.CreateViewStream(0, fs.Length - 1, MemoryMappedFileAccess.Read)) 
    {
        XDocument doc = XDocument.Load(str); // lê a partir do stream
        Console.WriteLine(doc.Root.Value);
    }
}

O segundo utiliza Memory-Mapped Files.
Um detalhe é que estes métodos copiam o conteúdo do arquivo para a memória, não é a coisa mais performática do mundo então tome cuidado ao fazer isso com um XML grande, e nunca se esqueça dos using para "descartar" seus Stream após o uso.
Boa sorte e espero ter ajudado.

