Skip to content

Instantly share code, notes, and snippets.

@qbg
Created October 15, 2011 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save qbg/1289728 to your computer and use it in GitHub Desktop.
Save qbg/1289728 to your computer and use it in GitHub Desktop.
DOM style streaming XML gist
The entire library is contained in the class XMLWriter.
== USAGE ==
Say we wanted to produce the following XML:
========
<?xml version="1.0" encoding="UTF-8"?>
<compiler-settings>
<speed>3</speed>
<safety>0</safety>
<debug foo="bar">0</debug>
<parent>
<child>42</child>
Lots of text
</parent>
</compiler-settings>
========
We can write the above XML to a path/File/OutputStream out with the following code:
========
XMLWriter compiler = new XMLWriter(out, "compiler-settings");
compiler.addSimpleElement("speed", "3");
compiler.addSimpleElement("safety", "0");
XMLWriter debug = compiler.addElement("debug");
debug.addAttribute("foo", "bar");
debug.addInlineText("0");
XMLWriter parent = compiler.addElement("parent");
parent.addSimpleElement("child", "42");
parent.addText("Lots of text");
compiler.close();
========
For my purposes, I've only needed the above features so far.
== Sample implementation ==
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
public class XMLWriter implements Closeable {
private static final String EOL = "\r\n";
private static final String INDENT = " ";
private Writer writer;
private boolean hasHeader = false;
private boolean isInline = true;
private XMLWriter lastChild = null;
private String name;
private int level;
private XMLWriter(String name, XMLWriter parent) {
this.writer = parent.writer;
this.name = name;
this.level = parent.level + 1;
writeStart();
}
private void createWriter(Writer writer, String name, String encoding) {
this.writer = writer;
this.name = name;
this.level = 0;
write("<?xml version=\"1.0\" encoding=\"");
write(encoding);
write("\"?>");
writeStart();
}
public XMLWriter(Writer writer, String name, String encoding) {
createWriter(writer, name, encoding);
}
private void createWriter(OutputStream os, String name) {
try {
createWriter(new OutputStreamWriter(os, "UTF-8"), name, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public XMLWriter(OutputStream os, String name) {
createWriter(os, name);
}
public XMLWriter(File file, String name) {
try {
OutputStream os = new FileOutputStream(file);
createWriter(os, name);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
public XMLWriter(String path, String name) {
try {
OutputStream os = new FileOutputStream(path);
createWriter(os, name);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
private void write(String text) {
try {
writer.write(text);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void writeEscape(String text) {
try {
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
switch (c) {
case '<':
writer.write("&lt;");
break;
case '>':
writer.write("&gt;");
break;
case '&':
writer.write("&amp;");
break;
case '"':
writer.write("&quot;");
break;
default:
writer.write(c);
break;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void writeStart() {
write(EOL);
indent(level);
write("<");
write(name);
}
private void indent(int n) {
for (int i = 0; i < n; i++) {
write(INDENT);
}
}
public void flush() {
try {
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void close() {
try {
finish();
write(EOL);
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void writeHeader() {
if (!hasHeader) {
write(">");
hasHeader = true;
}
}
private void writeFinish() {
writeHeader();
if (lastChild != null) {
lastChild.finish();
lastChild = null;
}
}
private void finish() {
if (!hasHeader) {
write(" />");
} else {
writeFinish();
if (!isInline) {
write(EOL);
indent(level);
}
write("</");
write(name);
write(">");
}
}
public void addAttribute(String attr, String value) {
write(" ");
write(attr);
write("=\"");
writeEscape(value);
write("\"");
}
public XMLWriter addElement(String name) {
writeFinish();
isInline = false;
lastChild = new XMLWriter(name, this);
return lastChild;
}
public void addText(String text) {
writeFinish();
isInline = false;
write(EOL);
indent(level + 1);
writeEscape(text);
}
public void addInlineText(String text) {
writeFinish();
writeEscape(text);
}
public void addSimpleElement(String name, String value) {
XMLWriter element = addElement(name);
element.addInlineText(value);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment