D'abord les choses d'abord, je ne peux pas changer la sortie du xml, il est produit par un tiers. Ils insèrent des caractères invalides dans le fichier XML. On me donne un InputStream de la représentation du flux d'octets du xml. Est-ce leur façon plus propre de filtrer les personnages offensants en plus de consommer le flux dans une chaîne et de le traiter? J'ai trouvé ceci: using a FilterReader mais cela ne fonctionne pas pour moi car j'ai un flux d'octets et pas un flux de caractères. Pour que cela vaille la peine, tout cela fait partie d'une procédure jmab unmarshalling, juste au cas où des options sont proposées.filtre/supprimer les caractères xml invalides du flux
Nous ne sommes pas prêts à jeter le flux entier s'il a de mauvais caractères. Nous avons décidé de les enlever et de continuer.
Voici un FilterReader que j'ai essayé de construire.
public class InvalidXMLCharacterFilterReader extends FilterReader
{
private static final Log LOG = LogFactory
.getLog(InvalidXMLCharacterFilterReader.class);
public InvalidXMLCharacterFilterReader(Reader in)
{
super(in);
}
public int read() throws IOException {
char[] buf = new char[1];
int result = read(buf, 0, 1);
if (result == -1)
return -1;
else
return (int) buf[0];
}
public int read(char[] buf, int from, int len) throws IOException {
int count = 0;
while (count == 0) {
count = in.read(buf, from, len);
if (count == -1)
return -1;
int last = from;
for (int i = from; i < from + count; i++) {
LOG.debug("" + (char)buf[i]);
if(!isBadXMLChar(buf[i]))
{
buf[last++] = buf[i];
}
}
count = last - from;
}
return count;
}
private boolean isBadXMLChar(char c)
{
if ((c == 0x9) ||
(c == 0xA) ||
(c == 0xD) ||
((c >= 0x20) && (c <= 0xD7FF)) ||
((c >= 0xE000) && (c <= 0xFFFD)) ||
((c >= 0x10000) && (c <= 0x10FFFF)))
{
return false;
}
return true;
}
}
Et voici comment je suis unmarshalling il:
jaxbContext = JAXBContext.newInstance(MyObj.class);
Unmarshaller unMarshaller = jaxbContext.createUnmarshaller();
Reader r = new InvalidXMLCharacterFilterReader(new BufferedReader(new InputStreamReader(is, "UTF-8")));
MyObj obj = (MyObj) unMarshaller.unmarshal(r);
et certains mauvais exemple xml
<?xml version="1.0" encoding="UTF-8" ?>
<foo>
bar
</foo>
Etes-vous sûr que * ils * insèrent des caractères non valides? N'est-ce pas vous qui lisez les caractères du flux binaire en utilisant le mauvais encodage et/ou en affichant les caractères lus en utilisant le mauvais encodage? – BalusC
Vous devriez vérifier le commentaire de BalusC. Si vous voulez continuer avec une implémentation FilteredReader, vous n'avez aucun problème à transformer le flux d'octets en un lecteur (en utilisant InputStreamReader), à condition que vous connaissiez le codage du flux d'octets. –
Je ne sais pas ce que BalusC veut dire. Ce sont des caractères XML 1.0 manifestement invalides. J'ai essayé d'utiliser un InputStreamReader (ainsi que l'emballage dans un lecteur tamponné) sans aucune chance. Je vais mettre à jour ma question avec du code. – DanInDC