2009-12-21 11 views
1

Je suis en train de créer un document XML (flux RSS) et j'ai résolu tous les problèmes, à l'exception d'un problème de codage de caractères. Le problème est que j'utilise un codage UTF-8 comme si <?xml version="1.0" encoding="UTF-8"?> sauf que le document lui-même n'est pas codé en UTF-8. J'utilise le package org.apache.ecs.xml pour créer toutes les balises. J'utilise ensuite doc.output(stream) pour écrire le contenu. Cette méthode ne semble pas écrire de sortie en utilisant UTF-8 et je ne sais pas comment y arriver. Jusqu'à ce que je le fais, certains symboles (la livre britannique est ce que j'ai remarqué pour la première fois) ne sont pas rendus correctement dans la plupart des lecteurs.Convertir un document XML de Latin1 en UTF8 en utilisant Java

--Updated avec plus information--

Je fini par utiliser une mauvaise solution (dans les commentaires comme expliqué) pour résoudre ce problème. La bonne réponse semble ne pas utiliser la bibliothèque org.apache.ecs.xml. Merci à tous pour votre aide. StackOverflow gagne à nouveau.

+1

Veuillez fournir un exemple de code qui montre comment vous utilisez le package 'org.apache.ecs.xml' et comment vous préparez l'objet' doc'. –

+0

Oh mon garçon ... d'où vient cette livre? Contrôle de l'interface graphique? Ligne de commande? Code en ligne? –

+0

Votre question/format est cool, pas de soucis et bienvenue! –

Répondre

1

Voici une solution trouvée par mon collègue que JE PENSE est la bonne façon de le faire mais qu'est-ce que je sais. Au lieu d'utiliser doc.output(stream) nous avons utilisé:

 try { 
      IOUtils.write(doc.toString(), stream, "UTF-8"); 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } 

Pour être honnête, je ne comprends pas encore complètement le problème, ce qui est la raison pour laquelle je rencontre des problèmes en premier lieu. Il semble que la solution de @ subamed a traversé et converti tout caractère que UTF-8 ne pouvait pas représenter et l'a remplacé par l'entité Unicode. Cette solution semble écrire dans le flux en utilisant le codage UTF-8 comme je le voulais initialement. Je ne connais pas la différence exacte, juste que les deux ont résolu mes problèmes. Tout autre commentaire pour m'aider à comprendre le problème serait apprécié.

+0

Cette solution semble vraiment bien, à condition que vous ayez accès à la bibliothèque commons-io. Ma solution a l'avantage de rendre la sortie indépendante de l'encodage, car elle ne contient que du pur ASCII. Cette solution utilise UTF-8 et encode les caractères étendus de la bonne manière, comme défini dans votre attribut de codage. La principale différence dans le résultat est que votre méthode met des caractères étendus dans 2 ou 3 octets, alors que le mien a besoin de 8 octets pour chacun. Mais XML est verbeux de toute façon. :) – glmxndr

0

Je ne suis pas au courant de ce paquet, mais de la source sur le web je soupçonne qu'il peut être rompu:

http://kickjava.com/src/org/apache/ecs/xml/XMLDocument.java.htm

contient des trucs comme

 for (int i=0; i<prolog.size(); i++) { 
268    ConcreteElement e = (ConcreteElement)prolog.elementAt(i); 
269    e.output(out); 
270    // XXX really this should use line separator! 
271 // XXX should also probably check for pretty print 
272 // XXX also probably have difficulties with encoding 

ce qui suggère des problèmes.

Nous utilisons XOM (http://www.xom.nu) et qui a spécifiquement un setEncoding() sur son sérialiseur je vous conseille donc de changer les paquets ...

+0

Malheureusement, j'ai vu cela mais j'espère qu'il y a une sorte de solution de contournement. Peu importe, merci pour la suggestion de paquet. – UmYeah

0

Voici une fonction que j'ai écrit pour convertir tous les caractères non-ASCII correspondant à leur entité. Cela pourrait vous aider à désinfecter du contenu PCDATA avant la sortie.

/** 
* Creates xml entities for non ascii characters in the given String. 
*/ 
public static String xmlEntitify(String in){ 

    StringBuffer b = new StringBuffer(); 

    for (int i=0;i<in.length();i++){ 

     Character c = in.charAt(i); 
     if (c<128){ 
      b.append(c); 
     } 
     else if (c=='\ufeff'){ 
      // BOM character, just remove it 
     } 
     else { 
      String cstr = Integer.toHexString(c).toUpperCase(); 
      while(cstr.length()<4){ 
       cstr="0"+cstr; 
      } 
      b.append("&#x"); 
      b.append(cstr); 
      b.append(";"); 
     } 
    } 
    return b.toString(); 
} 

Lire votre flux d'entrée dans un String content et écrire dans le flux de sortie xmlEntitify(content).

Votre sortie est garanti pour contenir uniquement des caractères ASCII, plus de problème d'encodage.

MISE À JOUR

Compte tenu des commentaires, je serai encore plus audacieux: si vous n'êtes pas désinfectante vos données, vous appelez des ennuis. Je suppose que vous remplacez au moins déjà les caractères < et & dans votre PCDATA. Si non, vous devriez certainement. J'ai une autre version de la méthode ci-dessus qui, au lieu de la première if, a:

if (c<128 && c!='&' && c!='<' && c!='>' && c!='"'){ 
    b.append(c); 
} 

pour que ces caractères sont également convertis en leur entité Unicode correspondant. Cela convertit tous mes PCDATA en chaînes ASCII uniquement compatibles Unicode. Je n'avais plus de problème d'encodage depuis que j'utilise cette technique. Je ne produis jamais de PCDATA XML qui n'a pas été passé par cette méthode: ce n'est pas balayer l'éléphant sous le tapis. C'est juste se débarrasser du problème en étant aussi générique que possible.

+0

Cela résout le problème. Il a besoin de coder en UTF-8 le flux de sortie, ce qui est TRÈS différent de substituer des entités de caractères pour des données non ASCII. Ces entités de caractère pointeront toujours vers les points de code Latin1, pas les points de code UTF-8 requis. –

+0

Comme Jim l'a écrit (et mon collègue m'a fait remarquer), cela ne fait que masquer le problème. Ceci est devenu ma solution temporaire juste parce que j'avais besoin d'une solution rapide mais quand j'aurai le temps je reviendrai et réécrirai mon code parce que c'est tout simplement faux. – UmYeah

+0

Haha, c'est génial. Je suis downvoted pour la seule réponse qui apporte quelque chose jusqu'ici. Je t'aime copains. @Jim: Je sais que je n'ai pas répondu à la question de la manière souhaitée. Si quelqu'un trouve une meilleure solution, je serais heureux de l'upvote et de l'utiliser dans mon propre code. Jusqu'à présent, l'assainissement du PCDATA a toujours été le meilleur moyen pour moi, ce qui fonctionne dans tous les cas. @UmYeah: lorsque vous n'avez que des caractères ASCII, votre texte est codé en UTF-8. Vous venez de changer la façon dont les caractères étendus sont appelés. Vous laissez au client la responsabilité de les formater. – glmxndr

1

La solution la plus simple va probablement être changer votre code comme suit:

XMLDocument doc = new XMLDocument(1.0,false,Charset.defaultCharset().toString()); 

Je devine qu'ils sont juste en utilisant l'encodage par défaut pour écrire des caractères dans le flux. Passez donc l'encodage par défaut au prologue et ça devrait aller. Je suis d'accord avec d'autres affiches que c'est probablement le moindre de vos soucis. En regardant le source repository pour ECS, il ne semble pas avoir été mis à jour depuis quatre ans (le référentiel "ECS2" de même).

Et une certaine autopromotion: si vous cherchez à construire des documents XML en utilisant une interface simple, la bibliothèque Practical XML a un constructeur. Il utilise le mécanisme de sérialisation JDK standard pour la sortie.

+1

Le 'Charset.defaultCharset()' renvoie le jeu de caractères par défaut spécifique à la plateforme, qui peut ne pas être le même que le codage du fichier XML et/ou ne pas être un dérivé Unicode, comme 'CP-1252' (ouch) ou 'ISO-8859-x'. Tu ne veux pas avoir ça. Vous devez connaître l'encodage actuel du fichier XML avant. – BalusC

+0

Si vous aviez lu la question de plus près, vous constateriez que l'OP est en train de * produire * et de fichier XML, sans en consommer un. Si vous aviez lu ma réponse de plus près, vous auriez vu que mon raisonnement pour utiliser 'defaultEncoding()' dans le prologue était qu'il semblait que la bibliothèque de tiers (Jakarta ECS) l'utilisait. – kdgregory

1

Toute chance que vous pouvez écrire à un écrivain plutôt qu'à un OutputStream ... de cette façon vous pouvez spécifier le codage.

Questions connexes