package net.sourceforge.mayfly.dump; import java.util.Stack; public class XmlWriter { // TODO: For mayfly, probably want a streaming version of this. private StringBuilder out = new StringBuilder(); private Stack openElements = new Stack(); public void startTag(String tag) { startTag(tag, new String[] {}); } public void startTag(String tag, String attributeName, String attributeValue) { startTag(tag, new String[] {attributeName, attributeValue}); } public void startTag(String tag, String[] attributes) { out.append("<"); tagName(tag); attributes(attributes); out.append(">"); openElements.push(tag); } private void tagName(String tag) { rejectCharacter(tag, '<'); rejectCharacter(tag, '&'); rejectCharacter(tag, '>'); rejectCharacter(tag, '\''); rejectCharacter(tag, '"'); out.append(tag); } private void rejectCharacter(String tag, char character) { if (tag.indexOf(character) != -1) { throw new XmlWriterException("Bad character " + character + " in start tag " + tag); } } private void attribute(String attributeName, String attributeValue) { out.append(" "); out.append(attributeName); out.append("=\""); out.append(attributeValue.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">") .replaceAll("\"", """)); out.append("\""); } private void attributes(String[] attributes) { for (int i = 0; i < attributes.length; i += 2) { attribute(attributes[i], attributes[i + 1]); } } public void endTag(String tag) { Object startTag = openElements.pop(); if (!tag.equals(startTag)) { throw new XmlWriterException( "end tag " + tag + " does not match start tag " + startTag); } out.append("</"); out.append(tag); out.append(">"); } public void singleTag(String tag, String[] attributes) { out.append("<"); tagName(tag); attributes(attributes); out.append(" />"); } public void singleTag(String tag) { singleTag(tag, new String[] {}); } public void singleTag(String tag, String attributeName, String attributeValue) { singleTag(tag, new String[] {attributeName, attributeValue}); } public String getOutput() { if (!openElements.isEmpty()) { throw new XmlWriterException("unclosed element " + openElements.peek()); } return out.toString(); } public void text(String text) { out.append(text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">")); } public void newline() { out.append('\n'); } public void indent(int spaces) { for (int i = 0; i < spaces; ++i) { out.append(' '); } } }