¿Cómo preservar las nuevas líneas en CDATA al generar XML?
Pregunta
Quiero escribir un texto que contenga caracteres de espacio en blanco como newline
y tab
en un archivo xml, así que uso
Element element = xmldoc.createElement("TestElement");
element.appendChild(xmldoc.createCDATASection(somestring));
pero cuando leí esto de nuevo usando
Node vs = xmldoc.getElementsByTagName("TestElement").item(0);
String x = vs.getFirstChild().getNodeValue();
Me sale una cadena que ya no tiene nuevas líneas.
Cuando miro directamente al xml en el disco, las nuevas líneas parecen conservadas. entonces el problema ocurre cuando se lee en el archivo xml.
¿Cómo puedo preservar las nuevas líneas?
¡Gracias!
Solución
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 W3C de hacerlo ( ver aquí ). 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
Otros consejos
Debe verificar el tipo de cada nodo usando node.getNodeType (). Si el tipo es CDATA_SECTION_NODE, debe concatenar los protectores CDATA a node.getNodeValue.
EDITAR: corta todas las cosas irrelevantes
Tengo curiosidad por saber qué implementación de DOM está utilizando, porque no refleja el comportamiento predeterminado de uno en un par de JVM que he probado (se envían con un Xerces impl). También estoy interesado en los caracteres de nueva línea que tiene su documento.
No estoy seguro de si CDATA debe preservar el espacio en blanco es un hecho. Sospecho que hay muchos factores involucrados. ¿Los DTD / esquemas no afectan la forma en que se procesa el espacio en blanco?
Puede intentar usar el xml: space = " preservar " atributo.
xml: space = 'preservar' no lo es. Eso es solo para " todos los espacios en blanco " nodos Es decir, si desea los nodos de espacios en blanco en
<this xml:space='preserve'> <has/>
<whitespace/>
</this>
Pero observe que esos nodos de espacios en blanco son SOLAMENTE espacios en blanco.
He estado luchando para que Xerces genere eventos que también permitan el aislamiento del contenido CDATA. Todavía no tengo solución.