2008-09-18 24 views
27

Tengo un archivo XML que es el resultado de una base de datos. Estoy usando el analizador Java SAX para analizar el XML y sacarlo en un formato diferente. El XML contiene algunos caracteres no válidos y el analizador arroja errores como 'Caracteres Unicode no válidos (0x5)'Descompresión de caracteres XML no válidos en Java

Hay una buena manera de quitar todos estos caracteres además de preprocesar el archivo línea por línea y reemplazarlos ? Hasta ahora me he encontrado con 3 diferentes caracteres inválidos (0x5, 0x6 y 0x7). Es un volcado de base de datos de ~ 4 gb y vamos a procesarlo un montón de veces, por lo que tener que esperar 30 minutos adicionales cada vez que obtengamos un nuevo volcado para ejecutar un preprocesador será un dolor, y esta no es la primera vez que me encuentro con este problema.

+2

¿Los personajes tienen algún significado? Es de suponer que no son corrupción al azar, por lo que no les quita la eliminación de información? –

+0

Si el archivo contiene caracteres no válidos, no es un archivo XML. Pídales a los creadores que creen solo XML bien formados en el futuro. He tenido este problema mucho en el pasado. La gente parece no entender que XML debe estar bien formado y no contener basura. – MarkR

+0

Estoy de acuerdo 100% Desafortunadamente no siempre es posible (personas tecnológicas incompetentes, redacción de contratos, etc.) – Mason

Respuesta

9

No he utilizado esto personalmente, pero Atlassian hecho un limpiador XML línea de comandos que pueden satisfacer sus necesidades (que se hizo principalmente para JIRA pero es XML XML):

Descargar atlassian-xml-cleaner-0.1.jar

abierto una consola DOS o un shell, y localice el archivo de copia de seguridad XML o ZIP en su computadora, aquí se supone que se llama data.xml

Ejecute: java -jar atlassian-xml-cleaner-0.1.jar data.xml> data -clean.xml

Esto escribirá una copia de data.xml a data-clean.xml, con los caracteres no válidos eliminados.

+0

¿El enlace está roto para cualquier otra persona? –

+0

@CyberneticTwerkGuruOrc Lo es. Aquí hay otro enlace que encontré: https://confluence.atlassian.com/download/attachments/12079/atlassian-xml-cleaner-0.1.jar?version=1&modificationDate=1307570821061&api=v2 – cyroxx

+0

Si construyes un add-on para el mercado , la misma clase que reemplaza caracteres no válidos está disponible en com.atlassian.core.util.xml.XMLCleaningReader –

0

¿Es posible que los caracteres no válidos estén presentes solo dentro de los valores y no las etiquetas en sí, es decir, el XML cumple el esquema pero los valores no se han desinfectado correctamente? Si es así, ¿qué hay sobre anular InputStream para crear un CleansingInputStream que reemplace tus caracteres inválidos con sus equivalentes XML?

0

Su problema no concierne a XML: se trata de codificaciones de caracteres. Lo que se reduce a esto es que cada cadena, ya sea XML u otra, consiste en bytes y no puede saber qué caracteres representan estos bytes, a menos que le digan qué carácter tiene la cadena. Si, por ejemplo, el proveedor le dice que es UTF-8 y en realidad es otra cosa, seguramente tendrá problemas. En el mejor de los casos, todo funciona, pero algunos bytes se traducen en caracteres "incorrectos". En el peor de los casos, obtienes errores como el que encontraste.

En realidad, su problema es aún peor: su cadena contiene secuencias de bytes que no representan caracteres en ninguna codificación de caracteres. No existe una herramienta de manejo de textos, y mucho menos un analizador XML, que pueda ayudarlo aquí. Esto necesita limpieza de nivel de byte.

6

utilizo la siguiente expresión regular que parece funcionar como se espera para el JDK6:

Pattern INVALID_XML_CHARS = Pattern.compile("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\uD800\uDC00-\uDBFF\uDFFF]"); 
... 
INVALID_XML_CHARS.matcher(stringToCleanup).replaceAll(""); 

En JDK7 que podría ser posible utilizar la notación \x{10000}-\x{10FFFF} para la última gama que se encuentra fuera de la BMP en lugar de la \uD800\uDC00-\uDBFF\uDFFF notación que no es tan simple de entender.

3

Tengo un problema similar al analizar el contenido de las tarifas de exportación australianas en un documento XML. No puedo usar las soluciones sugeridas aquí, como: - Use una herramienta externa (un jar) invocada desde la línea de comandos. - Solicite a la aduana australiana que limpie el archivo fuente.

El único método para resolver este problema en este momento es recorrer todo el contenido del archivo fuente, carácter por carácter y probar si cada carácter no pertenece al rango ascii 0x00 a 0x1F inclusive. Se puede hacer, pero me preguntaba si existe una forma mejor de usar métodos Java para el tipo String.

EDIT Encontré una solución que puede ser útil para otros: Utilice el método de Java String # ReplaceAll para reemplazar o eliminar cualquier carácter no deseado en el documento XML.

código Ejemplo (I eliminado algunas declaraciones necesarias para evitar el desorden):

BufferedReader reader = null; 
... 
String line = reader.readLine().replaceAll("[\\x00-\\x1F]", ""); 

En este ejemplo se quita (es decir, sustituir con una cadena vacía), caracteres no imprimibles dentro del rango 0x00 a 0x1F inclusive. Puede cambiar el segundo argumento en el método #replaceAll() para reemplazar caracteres con la cadena que requiere su aplicación.

20

que utilizan Xalan clase org.apache.xml.utils.XMLChar:

public static String stripInvalidXmlCharacters(String input) { 
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < input.length(); i++) { 
     char c = input.charAt(i); 
     if (XMLChar.isValid(c)) { 
      sb.append(c); 
     } 
    } 

    return sb.toString(); 
} 
+0

Creo que este no funcionará para caracteres sustitutos: 'XMLChar # isValid()' devolverá falso para las partes altas y bajas por separado, pero devolvería verdadero si el par juntos fuera válido. – ankon

Cuestiones relacionadas