2009-08-01 13 views
6

Quiero escribir un texto que contiene caracteres de espacio en blanco como newline y tab en un archivo XML, así que uso¿Cómo preservar nuevas líneas en CDATA al generar XML?

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

pero cuando leí esto de nuevo en el uso de

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

consigo una cadena que ya no tiene nuevas líneas.
Cuando miro directamente al xml en el disco, las nuevas líneas parecen conservarse. entonces el problema ocurre cuando se lee en el archivo xml.

¿Cómo puedo preservar las nuevas líneas?

Gracias!

+2

¿Podría publicar un ejemplo de código más completo? – skaffman

+0

es un Elemento. Publicaré más código pronto. – clamp

+0

cuando obtiene el valor de 'x', es equivalente a 'somestring' menos las nuevas líneas? – akf

Respuesta

5

Pongo No sé cómo analiza y escribe su documento, pero aquí hay un ejemplo de código mejorado basado en el suyo:

// 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 serialización con LSSerializer es la forma de hacerlo del W3C (see here). El resultado es el esperado, con separadores de línea:

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

gracias, lo intenté pero no funciona para mí. Aunque puedo ver que los saltos de línea están ahí en xmlfile en el disco, una vez que los leí de nuevo con este código, desaparecieron. tal vez mi personaje de linebreak es malo. ¿Cómo puedo averiguar cuál es? – clamp

+0

La salida que mostré es una salida real de mi propia máquina del ejemplo de código que publiqué. ¿Intentó escribir el texto con el código que sugerí? ¿O solo para leerlo usando mi código? Además, ¿cuál es la codificación de su archivo (puede ver que en mi ejemplo, la codificación es UTF-16). Tuve un problema similar al no usar la misma codificación, y lo arreglé usando Charset.forName() con la codificación real utilizada. –

+0

sí, probé tu código real en mi caso. utilicé exactamente el mismo código para dar salida a la cadena. pero no contiene espacios en blanco. la codificación que uso es encoding = "ISO-8859-1" intentaré usar UTF-16 – clamp

0

EDIT: cortar todas las cosas irrelevantes

Tengo curiosidad por saber qué implementación DOM que está utilizando, ya que no refleja el comportamiento predeterminado de la que en un par de JVM He intentado (se envían con una impl Xerces). También me interesan los nuevos caracteres que tiene su documento.

No estoy seguro de si CDATA debe preservar los espacios en blanco es un hecho. Sospecho que hay muchos factores involucrados. ¿Los DTD/esquemas no afectan cómo se procesa el espacio en blanco?

Puede intentar usar el atributo xml: space = "preserve".

+0

sí lo sé, es por eso que uso getFirstchild() – clamp

+0

¡Uh! ¡Perdió eso! – McDowell

+0

gracias, ¿dónde exactamente debería agregar ese atributo xml: space = "preserve"? al nodo que contiene el texto o la raíz xml? – clamp

2

Debe verificar el tipo de cada nodo utilizando node.getNodeType(). Si el tipo es CDATA_SECTION_NODE, necesita concaturar las guardias CDATA a node.getNodeValue.

+0

sí, el tipo de nodo es CDATA. pero, ¿qué quieres decir con guardias concat CDATA? – clamp

2

No tiene que usar necesariamente CDATA para conservar los caracteres de espacio en blanco. El XML specification especifica cómo codificar estos caracteres.

Así, por ejemplo, si tiene un elemento con valor que contiene un nuevo espacio que debe codificarlo con el regreso

&#xA; 

carro:

&#xD; 

Y así sucesivamente

+0

gracias, pero ¿hay alguna manera de codificarlo? para que pueda ver el texto formateado en el archivo xml en sí – clamp

0

xml: space = 'preserve' no es eso. Eso es solo para los nodos "all whitespace". Es decir, si desea que los nodos de espacio en blanco en

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

Pero se ve que esos nodos de espacio en blanco son sólo espacios en blanco.

He estado luchando para obtener Xerces para generar eventos que permitan el aislamiento del contenido CDATA. No tengo solución todavía.