2009-08-01 5 views
6

Je veux écrire un texte qui contient des caractères blancs tels que newline et tab dans un fichier xml donc j'utiliseComment conserver les nouvelles lignes dans CDATA lors de la génération de XML?

Element element = xmldoc.createElement("TestElement"); 
element.appendChild(xmldoc.createCDATASection(somestring)); 

mais quand je lis ce retour à l'aide

Node vs = xmldoc.getElementsByTagName("TestElement").item(0); 
String x = vs.getFirstChild().getNodeValue(); 

Je reçois une chaîne qui n'a plus de nouvelle ligne.
Lorsque je regarde directement dans le xml sur le disque, les retours à la ligne semblent conservés. le problème se produit donc lors de la lecture dans le fichier xml.

Comment puis-je préserver les retours à la ligne?

Merci!

+2

Pourriez-vous poster un exemple de code plus complet? – skaffman

+0

c'est un élément. Je posterai plus de code bientôt. – clamp

+0

lorsque vous obtenez la valeur de 'x', cela équivaut à 'somestring' moins les nouvelles lignes? – akf

Répondre

5

Je don Ne sais pas comment analyser et écrire votre document, mais voici un exemple de code amélioré basé sur le vôtre:

// creating the document in-memory               
Document xmldoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 

Element element = xmldoc.createElement("TestElement");          
xmldoc.appendChild(element);                
element.appendChild(xmldoc.createCDATASection("first line\nsecond line\n"));    

// serializing the xml to a string               
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();    

DOMImplementationLS impl =                 
    (DOMImplementationLS)registry.getDOMImplementation("LS");        

LSSerializer writer = impl.createLSSerializer();           
String str = writer.writeToString(xmldoc);             

// printing the xml for verification of whitespace in cdata        
System.out.println("--- XML ---");               
System.out.println(str);                 

// de-serializing the xml from the string             
final Charset charset = Charset.forName("utf-16");           
final ByteArrayInputStream input = new ByteArrayInputStream(str.getBytes(charset));  
Document xmldoc2 = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input); 

Node vs = xmldoc2.getElementsByTagName("TestElement").item(0);       
final Node child = vs.getFirstChild();              
String x = child.getNodeValue();               

// print the value, yay!                 
System.out.println("--- Node Text ---");             
System.out.println(x);                  

La sérialisation à l'aide de LSSerializer est la méthode W3C (see here). La sortie est comme prévu, avec des séparateurs de lignes:

--- XML --- 
<?xml version="1.0" encoding="UTF-16"?> 
<TestElement><![CDATA[first line 
second line ]]></TestElement> 
--- Node Text --- 
first line 
second line 
+1

merci, j'ai essayé mais ça ne marche pas pour moi. alors que je peux voir les sauts de ligne sont là dans le fichier xml sur le disque, une fois que je les relire avec ce code, ils sont partis. peut-être que mon personnage de linebreak est mauvais. comment puis-je savoir, lequel c'est? – clamp

+0

La sortie que j'ai montrée est une sortie réelle de ma propre machine de l'exemple de code que j'ai posté. Avez-vous essayé d'écrire le texte avec le code que j'ai suggéré? Ou seulement pour le lire en utilisant mon code? Aussi, quel est le codage de votre fichier (vous pouvez voir que dans mon exemple, l'encodage est UTF-16). J'ai eu un problème similaire en n'utilisant pas le même encodage, et je l'ai corrigé en utilisant Charset.forName() avec le codage utilisé. –

+0

Oui, j'ai essayé votre code réel dans mon cas. J'ai utilisé exactement le même code pour sortir la chaîne. mais il ne contient pas d'espaces. le codage que j'utilise est encoding = "ISO-8859-1" J'essaierai d'utiliser UTF-16 – clamp

0

EDIT: couper toutes les choses hors de propos

Je suis curieux de savoir ce que la mise en œuvre DOM que vous utilisez, car il ne reflète pas le comportement par défaut de celui dans quelques JVMs J'ai essayé (Ils sont livrés avec un Xerces impl). Je suis également intéressé par les nouveaux caractères de votre document.

Je ne suis pas sûr si CDATA devrait préserver les espaces est une donnée. Je soupçonne qu'il y a beaucoup de facteurs impliqués. Les DTD/schémas n'ont-ils pas d'incidence sur le traitement des espaces?

Vous pouvez essayer d'utiliser l'attribut xml: space = "preserve".

+0

oui je sais, c'est pourquoi j'utilise getFirstchild() – clamp

+0

Euh! Manqué ça! – McDowell

+0

merci, où devrais-je ajouter cet attribut xml: space = "preserve"? au noeud qui contient le texte ou à la racine xml? – clamp

2

Vous devez vérifier le type de chaque noeud à l'aide de node.getNodeType(). Si le type est CDATA_SECTION_NODE, vous devez concaténer les gardes CDATA à node.getNodeValue.

+0

oui, le type du noeud est CDATA. mais que voulez-vous dire avec les gardes CDATA concat? – clamp

2

Vous n'avez pas nécessairement besoin d'utiliser CDATA pour conserver les caractères en espace blanc. Le code XML specification spécifie comment coder ces caractères.

Ainsi, par exemple, si vous avez un élément avec une valeur qui contient un nouvel espace, vous devez encoder avec

&#xA; 

Retour chariot:

&#xD; 

Et ainsi de suite

+0

merci, mais est-il un moyen sans l'encoder? afin que je puisse voir le texte formaté dans le fichier xml lui-même? – clamp

0

xml: space = 'preserve' n'est-ce pas. C'est seulement pour les nœuds "tout espace". Autrement dit, si vous voulez les nœuds blancs dans

<this xml:space='preserve'> <has/> 
<whitespace/> 
</this> 

Mais voyez que ces nœuds blancs sont que des espaces.

J'ai eu du mal à faire en sorte que Xerces génère des événements permettant l'isolation du contenu CDATA. Je n'ai pas encore de solution.

Questions connexes