Supprimer les caractères XML non valides en Java

J’ai un fichier XML qui est la sortie d’une firebase database. J’utilise l’parsingur Java SAX pour parsingr le XML et le sortir dans un format différent. Le XML contient des caractères non valides et l’parsingur génère des erreurs telles que “Caractère Unicode non valide (0x5)”.

Existe-t-il un bon moyen de supprimer tous ces caractères en dehors du traitement préalable du fichier ligne par ligne et de son remplacement? Jusqu’à présent, j’ai rencontré 3 différents caractères non valides (0x5, 0x6 et 0x7). C’est un vidage de la firebase database ~ 4 Go et nous allons le traiter à plusieurs resockets, donc devoir attendre 30 minutes supplémentaires chaque fois que nous obtenons un nouveau dump pour exécuter un pré-processeur, ça va être difficile, et ce n’est pas la première fois que je rencontre ce problème.

Je ne l’ai pas utilisé personnellement, mais Atlassian a créé un nettoyeur XML en ligne de commande qui peut répondre à vos besoins (il a été conçu principalement pour JIRA mais XML est XML):

Télécharger atlassian-xml-cleaner-0.1.jar

Ouvrez une console ou un shell DOS et localisez le fichier de sauvegarde XML ou ZIP sur votre ordinateur, appelé ici data.xml.

Exécuter: java -jar atlassian-xml-cleaner-0.1.jar data.xml> data-clean.xml

Cela écrira une copie de data.xml dans data-clean.xml, avec les caractères non valides supprimés.

J’ai utilisé la classe org.apache.xml.utils.XMLChar Xalan:

 public static Ssortingng ssortingpInvalidXmlCharacters(Ssortingng input) { SsortingngBuilder sb = new SsortingngBuilder(); for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); if (XMLChar.isValid(c)) { sb.append(c); } } return sb.toString(); } 

J’utilise l’expression rationnelle suivante qui semble fonctionner comme prévu pour le JDK6:

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

Dans JDK7, il est possible d’utiliser la notation \x{10000}-\x{10FFFF} pour la dernière plage située en dehors du BMP au lieu de la \uD800\uDC00-\uDBFF\uDFFF qui n’est pas aussi simple à comprendre.

J’ai un problème similaire lors de l’parsing du contenu d’un tarif d’exportation australien dans un document XML. Je ne peux pas utiliser les solutions suggérées ici telles que: – Utiliser un outil externe (un jar) appelé depuis la ligne de commande. – Demander aux douanes australiennes de nettoyer le fichier source.

La seule méthode pour résoudre ce problème pour le moment est de parcourir l’intégralité du contenu du fichier source, caractère par caractère et de tester si chaque caractère n’appartient pas à la plage ascii 0x00 à 0x1F inclusivement. Cela peut être fait, mais je me demandais s’il y avait un meilleur moyen d’utiliser les méthodes Java pour le type Ssortingng.

EDIT J’ai trouvé une solution qui pourrait être utile aux autres: Utilisez la méthode Java Ssortingng # ReplaceAll pour remplacer ou supprimer les caractères indésirables dans un document XML.

Exemple de code (j’ai supprimé certaines instructions nécessaires pour éviter l’encombrement):

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

Dans cet exemple, je supprime (remplacer par une chaîne vide) des caractères non imprimables compris entre 0x00 et 0x1F inclusivement. Vous pouvez modifier le deuxième argument dans la méthode #replaceAll () pour remplacer les caractères par la chaîne requirejse par votre application.

Est-il possible que vos caractères non valides ne soient présents que dans les valeurs et non dans les tags eux-mêmes, c’est-à-dire que le XML répond théoriquement au schéma mais que les valeurs n’ont pas été correctement filtrées? Si oui, pourquoi ne pas passer par InputStream pour créer un CleansingInputStream qui remplace vos caractères non valides par leurs équivalents XML?

Votre problème ne concerne pas le XML: il concerne les encodages de caractères. En fait, chaque chaîne, XML ou autre, consiste en octets et vous ne pouvez pas savoir quels sont les caractères représentés par ces octets, à moins que vous ne sachiez quel est le caractère codé de la chaîne. Si, par exemple, le fournisseur vous dit qu’il s’agit de UTF-8 et qu’il s’agit de quelque chose d’autre, vous risquez de rencontrer des problèmes. Dans le meilleur des cas, tout fonctionne, mais certains octets sont traduits en “mauvais” caractères. Dans le pire des cas, vous obtenez des erreurs comme celle que vous avez rencontrée.

En fait, votre problème est encore pire: votre chaîne contient des séquences d’octets qui ne représentent aucun caractère dans aucun encodage de caractères. Il n’y a pas d’outil de traitement de texte, encore moins un parsingur XML, qui peut vous aider ici. Cela nécessite un nettoyage au niveau des octets.