'Invalid Character exception' problemas al deserializar XML

La serialización, deserialización de objetos utilizando un archivo xml para almacenarlos o transferirlos es una herramienta muy útil. El problema es que en los archivos xml no están permitidos todos los caracteres. Si somos cuidadosos serializando nos podremos evitar este tipo de problemas. El verdadero problema se presenta cuando estos xml no los generamos nosotros, sino que nos los proporciona una organización externa a nuestra empresa, y no existe la posibilidad o la voluntad, de cambiarlos. En este caso el peor problema es que el xml nos venga con caracteres inválidos, dándonos una excepción de "Invalid Character".
Dada una función de deserialización del tipo:
 
        public static T DeserializeXMLToObject(string xmlText)
        {
            T lResult = default(T);
            if (string.IsNullOrEmpty(xmlText)) return lResult;

            XmlSerializer xs = new XmlSerializer(typeof(T));
            using (MemoryStream sr = new MemoryStream(UTF8Encoding.UTF8.GetBytes(xmlText)))
            {
                XmlTextReader xtr = new XmlTextReader(sr);
                lResult = (T)xs.Deserialize(xtr);
            }
            return lResult;
        }
Nos encontraremos con problemas cuando el xml no esté bien formado, para evitarlo añadiremos una función de limpieza de caracteres inválidos de la siguiente manera:
 
        public static string RemoveInvalidCharacters(string str)
        {
            string stFormD = str.Normalize(NormalizationForm.FormD);
            StringBuilder sb = new StringBuilder();

            for (int ich = 0; ich < stFormD.Length; ich++)
            {
                UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
                if (uc != UnicodeCategory.NonSpacingMark)
                {
                    sb.Append(stFormD[ich]);
                }
            }
            return (sb.ToString().Normalize(NormalizationForm.FormC));
        }
Dejando la función de deserialización de la siguiente manera:
 
        public static T DeserializeXMLToObject(string xmlText)
        {
            T lResult = default(T);
            if (string.IsNullOrEmpty(xmlText)) return lResult;

            XmlSerializer xs = new XmlSerializer(typeof(T));
            using (MemoryStream sr = new MemoryStream(UTF8Encoding.UTF8.GetBytes(RemoveInvalidCharacters(xmlText))))
            {
                XmlTextReader xtr = new XmlTextReader(sr);
                lResult = (T)xs.Deserialize(xtr);
            }
            return lResult;
        }
Con esta sencilla función eliminamos los caracteres conflictivos pudiendo generarse el xml sin problemas.

No hay comentarios:

Publicar un comentario