Como preservar newlines em CDATA quando gerar XML?
Pergunta
Eu quero escrever algum texto que contém caracteres em branco como newline
e tab
em um arquivo xml então eu uso
Element element = xmldoc.createElement("TestElement");
element.appendChild(xmldoc.createCDATASection(somestring));
mas quando eu li isso novamente usando
Node vs = xmldoc.getElementsByTagName("TestElement").item(0);
String x = vs.getFirstChild().getNodeValue();
Eu recebo uma cadeia que não tem newlines mais.
Quando eu olhar diretamente para o xml no disco, as novas linhas parecem preservada. de modo que o problema ocorre quando a leitura no arquivo xml.
Como posso preservar as quebras de linha?
Obrigado!
Solução
Eu não sei como você analisar e escrever o seu documento, mas aqui está um exemplo de código aprimorado com base na sua:
// 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);
A serialização usando LSSerializer é a maneira W3C para fazê-lo ( veja aqui ). A saída é a esperada, com separadores de linha:
--- XML ---
<?xml version="1.0" encoding="UTF-16"?>
<TestElement><![CDATA[first line
second line ]]></TestElement>
--- Node Text ---
first line
second line
Outras dicas
Você precisa verificar o tipo de cada nó usando node.getNodeType (). Se o tipo é CDATA_SECTION_NODE, você precisa concat os guardas CDATA para node.getNodeValue.
Você não necessariamente tem que usar CDATA para preservar espaços em branco. O XML especificação especificar como codificar esses caracteres.
Assim, por exemplo, se você tem um elemento com valor que contém um novo espaço que você deve codificá-lo com


Retorno de carro:

E assim por diante
EDIT: corte todo o material irrelevante
Estou curioso para saber o que a implementação DOM que você está usando, porque não espelhar o comportamento padrão de um em um par de JVMs que eu tentei (eles navio com uma impl Xerces). Eu também estou interessado no que caracteres de nova linha o documento tiver.
Eu não tenho certeza se se CDATA deve preservar espaço em branco é um dado. Eu suspeito que há muitos fatores envolvidos. Não DTDs / esquemas afetar a forma como o espaço em branco é processado?
Você pode tentar usar o xml:. Space = "preserve" atributo
xml: space = 'preserve' não é isso. Isso é apenas para nós "todos os espaços em branco". Ou seja, se você deseja que o espaço em branco nós em
<this xml:space='preserve'> <has/>
<whitespace/>
</this>
Mas ver que esses nós de espaço em branco são apenas espaços em branco.
Eu tenho lutado para obter Xerces para gerar eventos que permitem o isolamento de conteúdo CDATA também. Eu não tenho nenhuma solução até agora.