Using Java, I would like to take a document in the following format:
I support @jtahlborn's answer. Just for completeness, I adapted his solution to completely remove the whitespace-only elements instead of just clearing them.
public static void stripEmptyElements(Node node)
{
NodeList children = node.getChildNodes();
for(int i = 0; i < children.getLength(); ++i) {
Node child = children.item(i);
if(child.getNodeType() == Node.TEXT_NODE) {
if (child.getTextContent().trim().length() == 0) {
child.getParentNode().removeChild(child);
i--;
}
}
stripEmptyElements(child);
}
}
Try this code. read
and write
methods in FileStream ignore whitespace and indents.
try {
File f1 = new File("source.xml");
File f2 = new File("destination.xml");
InputStream in = new FileInputStream(f1);
OutputStream out = new FileOutputStream(f2);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0){
out.write(buf, 0, len);
}
in.close();
out.close();
System.out.println("File copied.");
} catch(FileNotFoundException ex){
System.out.println(ex.getMessage() + " in the specified directory.");
System.exit(0);
} catch(IOException e7){
System.out.println(e7.getMessage());
}
As documented in an answer to another question, the relevant function would be DocumentBuilderFactory.setIgnoringElementContentWhitespace(), but - as pointed out here already - that function requires the use of a validating parser, which requires an XML schema, or some such.
Therefore, your best bet is to iterate through the Document you get from the parser, and remove all nodes of type TEXT_NODE (or those TEXT_NODEs which contain only whitespace).
Working solution following instructions in the question's comments by @Luiggi Mendoza.
public static String trim(String input) {
BufferedReader reader = new BufferedReader(new StringReader(input));
StringBuffer result = new StringBuffer();
try {
String line;
while ( (line = reader.readLine() ) != null)
result.append(line.trim());
return result.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
recursively traverse the document. remove any text nodes with blank content. trim any text nodes with non-blank content.
public static void trimWhitespace(Node node)
{
NodeList children = node.getChildNodes();
for(int i = 0; i < children.getLength(); ++i) {
Node child = children.item(i);
if(child.getNodeType() == Node.TEXT_NODE) {
child.setTextContent(child.getTextContent().trim());
}
trimWhitespace(child);
}
}
Java8+transformer does not create any but Java10+transformer puts everywhere empty lines. I still want to keep a pretty indents. This is my helper function to create xml string from any DOMElement instance such as doc.getDocumentElement()
root node.
public static String createXML(Element elem) throws Exception {
DOMSource source = new DOMSource(elem);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
//transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes");
transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
transformer.transform(source, result);
// Java10-transformer adds unecessary empty lines, remove empty lines
BufferedReader reader = new BufferedReader(new StringReader(writer.toString()));
StringBuilder buf = new StringBuilder();
try {
final String NL = System.getProperty("line.separator", "\r\n");
String line;
while( (line=reader.readLine())!=null ) {
if (!line.trim().isEmpty()) {
buf.append(line);
buf.append(NL);
}
}
} finally {
reader.close();
}
return buf.toString(); //writer.toString();
}