Analyser un fichier XML à l'aide de l'analyseur DOM Java DOM donne:
[Fatal Error] os__flag_8c.xml:103:135: An invalid XML character (Unicode: 0xc) was found in the element content of the document.
org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0xc) was found in the element content of the document.
at com.Sun.org.Apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
at com.Sun.org.Apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
Il y a quelques caractères qui ne sont pas autorisés dans les documents XML, même lorsque vous encapsulez des données dans des blocs CDATA.
Si vous avez généré le document, vous devrez entité le coder ou dépouiller. Si vous avez un document contenant des erreurs, vous devez supprimer ces caractères avant d'essayer de l'analyser.
Voir la réponse de dolmens dans ce fil: caractères non valides en XML
Où il renvoie à cet article: http://www.w3.org/TR/xml/#charsets
Fondamentalement, tous les caractères inférieurs à 0x20 sont interdits, sauf 0x9 (TAB), 0xA (CR?), 0xD (LF?)
public String stripNonValidXMLCharacters(String in) {
StringBuffer out = new StringBuffer(); // Used to hold the output.
char current; // Used to reference the current character.
if (in == null || ("".equals(in))) return ""; // vacancy test.
for (int i = 0; i < in.length(); i++) {
current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen.
if ((current == 0x9) ||
(current == 0xA) ||
(current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF)))
out.append(current);
}
return out.toString();
}
Le caractère 0x0C n'est pas valide dans XML 1.0 mais serait un caractère valide dans XML 1.1 . Donc, sauf si le fichier xml spécifie la version 1.1 dans le prologue, il est tout simplement invalide et vous devez vous plaindre auprès du producteur de ce fichier.
Ce lien a un code Java qui fonctionne parfaitement bien.
http://blog.mark-mclaren.info/2007/02/invalid-xml-characters-when-valid-utf8_5873.html
Chaque fois qu'un caractère xml invalide vient xml, il donne une telle erreur. Lorsque vous l'ouvrez dans notepad ++, cela ressemble à VT, SOH, FF comme ceux-ci sont des caractères xml invalides. J'utilise xml version 1.0 et je valide les données texte avant de les entrer dans la base de données par modèle
Pattern p = Pattern.compile("[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFF]+");
retunContent = p.matcher(retunContent).replaceAll("");
Il s'assurera qu'aucun caractère spécial invalide n'entrera en XML
Vous pouvez filtrer tous les caractères "non valides" avec une classe FilterReader personnalisée:
public class InvalidXmlCharacterFilter extends FilterReader {
protected InvalidXmlCharacterFilter(Reader in) {
super(in);
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
int read = super.read(cbuf, off, len);
if (read == -1) return read;
for (int i = off; i < off + read; i++) {
if (!XMLChar.isValid(cbuf[i])) cbuf[i] = '?';
}
return read;
}
}
Et lancez-le comme ceci:
InputStream fileStream = new FileInputStream(xmlFile);
Reader reader = new BufferedReader(new InputStreamReader(fileStream, charset));
InvalidXmlCharacterFilter filter = new InvalidXmlCharacterFilter(reader);
InputSource is = new InputSource(filter);
xmlReader.parse(is);
Toutes ces réponses semblent supposer que l'utilisateur génère le mauvais XML, plutôt que de le recevoir de gSOAP, ce qui devrait être mieux connu!
Pour les personnes qui lisent un tableau d'octets dans une chaîne et tentent de se convertir en objet avec JAXB, vous pouvez ajouter un codage "iso-8859-1" en créant une chaîne à partir d'un tableau d'octets comme ceci:
String JAXBallowedString = new String (entrée octet [], "iso-8859-1");
Cela remplacerait l'octet en conflit par un codage à un octet que JAXB peut gérer. Évidemment, cette solution consiste uniquement à analyser le xml.
J'ai rencontré un problème similaire où XML contenait des caractères de contrôle. Après avoir examiné le code, j'ai constaté qu'une classe obsolète, StringBufferInputStream, était utilisée pour lire le contenu des chaînes.
http://docs.Oracle.com/javase/7/docs/api/Java/io/StringBufferInputStream.html
This class does not properly convert characters into bytes. As of JDK 1.1, the preferred way to create a stream from a string is via the StringReader class.
Je l'ai changé en ByteArrayInputStream et cela a bien fonctionné.