2009-04-29 11 views
1

J'ai une exigence bizarre où je dois prendre du xml et le réécrire pour que les nœuds de texte soient enveloppés dans CDATA (ceci est pour un client qui ne permettra pas l'échappement normal).Meilleure façon de convertir xml pour avoir du CDATA autour du texte (en java)

Il ne semble pas que les bibliothèques XML normales dom4j, jdom, java xml aient un support intégré pour cela. Des idées? Puis-je utiliser XSLT pour cela?

Je n'étais pas très clair. Voici ce que je vais commencer par:

<foo>This has an &amp; escaped value</foo> 

Ce que je dois faire est de convertir en:

<foo><![CDATA[This has an & escaped value]]></foo> 

-Dave

+0

Que voulez-vous dire «un client qui ne permet pas l'échappement normal»? Il semble que vous envoyez un fichier XML à un programme qui ne peut pas traiter XML. Est-ce vraiment ce qui se passe? –

Répondre

2

Vous pouvez utiliser XSLT pour ce faire, à condition que: a) tout le texte que vous avez besoin de produire soit en éléments, b) vous vous souciez seulement des nœuds de texte, c) vous connaissez les noms de tous les éléments qui contiennent text, et d) il est possible d'émettre du texte dans tous ces éléments de sortie en tant que CDATA. Si tous ces cas sont vraies, alors vous pouvez écrire une transformation d'identité et d'ajouter cet élément à lui:

<xsl:output method="xml" cdata-section-elements="elm1 elm2 elm3..."/> 

Voir the W3C XSLT recommendation à ce sujet.

0

Prendre premade xml et l'analyse syntaxique (avec un analyseur XML) ça va juste faire exploser l'analyseur sur les caractères non-évanouis. La seule solution à laquelle je peux penser est de créer votre propre analyseur de soupes pour l'analyser, le modifier et le renvoyer à xml.

+0

Dans ce cas, les fichiers xml de début et de fin sont valides, en utilisant simplement différentes manières d'échapper les données. – Dave

1

Je pense que cela pourrait fonctionner avec une transformation XSLT, mais je ne suis pas sûr en ce qui concerne les performances de la transformation. Jetez un oeil à CDATA Sections and XSLT, il peut vous aider.

+0

Cela pourrait fonctionner, mais oui, je vais devoir vérifier la performance. Merci! – Dave

3

Merci pour toutes vos réponses. J'ai trouvé un moyen de le faire en utilisant dom4j. Ma mise en œuvre ne fonctionne pas si les éléments ont des enfants "mixtes" (c'est-à-dire un élément de texte), mais dans mon cas ce n'est pas un problème. Cela fonctionne parce que dom4j sortira CDATA si vous ajoutez des noeuds CDATA:

public void replaceTextWithCdataNoMixedText(Document doc) { 
     if(doc == null) 
      return; 
     replaceTextWithCdata(doc.content()); 
    } 

    private void replaceTextWithCdata(List content) { 
     if (content == null) 
      return; 
     for (Object o : content) { 
      if (o instanceof Element) { 
       Element e = (Element) o; 
       String t = e.getTextTrim(); 
       if (textNeedsEscaping(t)) { 
        e.clearContent(); 
        e.addCDATA(t); 
       } else { 
        List childContent = e.content(); 
        replaceTextWithCdata(childContent); 
       } 
      } 
     } 
    } 


    private boolean textNeedsEscaping(String t) { 
     if (t == null) 
      return false; 
     for (int i = 0; i < t.length(); i++) { 
      char c = t.charAt(i); 
      if (c == '<' || c == '>' || c == '&') { 
       return true; 
      } 
     } 
     return false; 
    } 
+0

A travaillé bien pour moi! Merci! –

+0

Soyez prudent avec ce code. Il appelle e.getTextTrim() qui va normaliser votre valeur de chaîne. J'avais un texte formaté qui continuait à être écrasé, et finalement suivi jusqu'à ici. J'ai remplacé par e.getText() pour un résultat plus précis. –

Questions connexes