Actuellement, je travaille sur une fonctionnalité qui implique l'analyse XML que nous recevons d'un autre produit. J'ai décidé d'exécuter des tests sur certaines données réelles des clients, et il semble que l'autre produit autorise la saisie d'utilisateurs qui devraient être considérés comme non valides. Quoi qu'il en soit, je dois encore essayer de trouver un moyen de l'analyser. Nous utilisons javax.xml.parsers.DocumentBuilder
Et j'obtiens une erreur d'entrée qui ressemble à ceci.
<xml>
...
<description>Example:Description:<THIS-IS-PART-OF-DESCRIPTION></description>
...
</xml>
Comme vous pouvez le constater, la description contient ce qui semble être une balise non valide (<THIS-IS-PART-OF-DESCRIPTION>
). Maintenant, cette balise de description est connue pour être une balise leaf et ne devrait pas contenir de balises imbriquées. Quoi qu'il en soit, c'est toujours un problème et génère une exception sur DocumentBuilder.parse(...)
Je sais que ce XML n'est pas valide, mais il est prévisible non valide. Des idées sur la façon d'analyser une telle entrée?
Ce "XML" est pire que invalide - c'est pas bien formé; voir Bien formé vs XML valide.
Une évaluation informelle de la prévisibilité des transgressions n'aide pas. Ces données textuelles ne sont pas XML. Aucun outil ou bibliothèque XML conforme ne peut vous aider à le traiter.
Utilisez un analyseur de balisage tolérant pour nettoyer le problème avant d'analyser en XML:
Autonome: xmlstarlet possède de solides capacités de récupération et de réparation crédit: RomanPerekhrest
xmlstarlet fo -o -R -H -D bad.xml 2>/dev/null
Autonome et C: HTML Tidy fonctionne également avec XML.
codecs.EncodedFile()
pour nettoyer les caractères illégaux.FilterInputStream
peut être utilisé pour nettoyage de prétraitement .XmlReaderSettings.ConformanceLevel
peut être réglé sur ConformanceLevel.Fragment
pour que XmlReader
peut lire entités XML bien formées sans élément racine.XmlReader.ReadToFollowing()
peut parfois être utilisé pour contourner les problèmes syntaxiques XML , mais notez la violation des règles avertissement dans # 3 ci-dessous.Microsoft.Language.Xml.XMLParser
est dit "tolérant aux erreurs".Traitez les données sous forme de texte manuellement à l'aide d'un éditeur de texte ou par programmation à l'aide de fonctions de caractères/chaînes. Faire cela par programme peut aller de délicat à impossible car ce qui semble souvent prévisible ne l'est pas - la violation des règles est rarement lié par des règles .
preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $s);
string.tr("^\u{0009}\u{000a}\u{000d}\u{0020}-\u{D7FF}\u{E000}-\u{FFFD}", ' ')
inputStr.replace(/[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm, '')
Pour esperluette , utilisez l'expression régulière pour remplacer les correspondances par &
: crédit: blhsin , demo
&(?!(?:#\d+|#x[0-9a-f]+|\w+);)
Notez que les expressions régulières ci-dessus ne prendront pas en compte les commentaires ou les sections CDATA.
Un analyseur XML standard n'acceptera JAMAIS du XML non valide, de par sa conception.
Votre seule option est de prétraiter l'entrée pour supprimer le contenu "prévisible invalide", ou de l'envelopper dans CDATA, avant de l'analyser.
OMI, ces cas doivent être résolus en utilisant JSoup .
Ci-dessous une réponse pas vraiment à ce cas spécifique, mais trouvée ceci sur le web (merci à inuyasha82 sur Coderwall). Ce bit de code m'a inspiré pour un autre problème similaire en traitant des XML malformés, donc je le partage ici.
Veuillez ne pas modifier ce qui est ci-dessous, tel qu'il est sur le site Web d'origine.
Le format XML, nécessite d'être valide un élément racine unique déclaré dans le document. Ainsi, par exemple, un xml valide est:
<root>
<element>...</element>
<element>...</element>
</root>
Mais si vous avez un document comme:
<element>...</element>
<element>...</element>
<element>...</element>
<element>...</element>
Ceci sera considéré comme un XML mal formé, donc de nombreux analyseurs xml lèvent juste une exception ne se plaignant d'aucun élément racine. Etc.
Dans cet exemple, il existe une solution pour résoudre ce problème et analyser avec succès le fichier XML mal formé ci-dessus.
Fondamentalement, ce que nous allons faire est d'ajouter par programmation un élément racine.
Vous devez donc tout d'abord ouvrir la ressource qui contient votre xml "malformé" (c'est-à-dire un fichier):
File file = new File(pathtofile);
Ouvrez ensuite un FileInputStream:
FileInputStream fis = new FileInputStream(file);
Si nous essayons d'analyser ce flux avec une bibliothèque XML à ce stade, nous lèverons l'exception de document mal formé.
Nous créons maintenant une liste d'objets InputStream avec trois éléments:
Un élément ByteIputStream qui contient la chaîne: "" Notre FileInputStream Un ByteInputStream avec la chaîne: "" Le code est donc:
List<InputStream> streams =
Arrays.asList(
new ByteArrayInputStream("<root>".getBytes()),
fis,
new ByteArrayInputStream("</root>".getBytes()));
Maintenant, en utilisant un SequenceInputStream, nous créons un conteneur pour la liste créée ci-dessus:
InputStream cntr =
new SequenceInputStream(Collections.enumeration(str));
Maintenant, nous pouvons utiliser n'importe quelle bibliothèque XML Parser, sur le cntr, et elle sera analysée sans aucun problème. (Vérifié avec la bibliothèque Stax);
La réponse acceptée est un bon conseil et contient des liens très utiles.
Je voudrais ajouter que cela, et beaucoupautres les cas de XML non bien formé et/ou invalide DTD peuvent être réparés en utilisant SGML, le sur-ensemble normalisé ISO de HTML et XML. Dans votre cas, ce qui fonctionne, c'est de déclarer le faux THIS-IS-PART-OF-DESCRIPTION
élément en tant qu'élément vide SGML, puis utilisez par exemple. le programme osx
(qui fait partie du package OpenSP/OpenJade SGML) pour le convertir en XML. Par exemple, si vous fournissez les éléments suivants à osx
<!DOCTYPE xml [
<!ELEMENT xml - - ANY>
<!ELEMENT description - - ANY>
<!ELEMENT THIS-IS-PART-OF-DESCRIPTION - - EMPTY>
]>
<xml>
<description>blah blah
<THIS-IS-PART-OF-DESCRIPTION>
</description>
</xml>
il produira un XML bien formé pour un traitement ultérieur avec les outils XML de votre choix.
Notez cependant que votre exemple d'extrait de code présente un autre problème dans le fait que les noms d'éléments commençant par les lettres xml
ou XML
ou Xml
etc. sont réservés en XML et ne le seront pas. être acceptée par les analyseurs XML conformes.