1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
package com.jclark.xsl.sax;
import org.xml.sax.*;
import java.io.Writer;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class NXMLOutputHandler implements OutputDocumentHandler {
class CharacterHandler {
void characters(char[] ch, int off, int len) throws IOException { }
}
class EscapeCharacterHandler extends CharacterHandler {
private int c;
private StringBuffer buf = new StringBuffer();
void characters(char[] ch, int off, int len) {
for (; len > 0; off++, len--) {
if (ch[off] == '\n')
buf.append(lineSeparator);
else
buf.append(ch[off]);
}
}
void setChar(String str) {
buf.setLength(0);
if (str.length() == 0)
c = -1;
else
c = str.charAt(0);
}
void endChar() {
if (c >= 0) {
if (c >= escapes.length) {
int newLen = escapes.length;
do {
newLen *= 2;
} while (newLen <= c);
String[] oldEscapes = escapes;
escapes = new String[newLen];
System.arraycopy(oldEscapes, 0, escapes, 0, oldEscapes.length);
}
escapes[c] = buf.toString();
}
}
}
class DataCharacterHandler extends CharacterHandler {
void characters(char[] ch, int off, int len) throws IOException {
final String[] escapes = NXMLOutputHandler.this.escapes;
int start = off;
for (; len > 0; off++, len--) {
char c = ch[off];
if (c < escapes.length) {
final String escaped = escapes[c];
if (escaped != null) {
if (start != off)
writer.write(ch, start, off - start);
writer.write(escaped);
start = off + 1;
}
}
}
if (start != off)
writer.write(ch, start, off - start);
}
}
class ControlCharacterHandler extends CharacterHandler {
void characters(char[] ch, int off, int len) throws IOException {
writer.write(ch, off, len);
}
}
class LineControlCharacterHandler extends CharacterHandler {
void characters(char[] ch, int off, int len) throws IOException {
int start = off;
for (; len > 0; off++, len--) {
if (ch[off] == '\n') {
if (start != off)
writer.write(ch, start, off - start);
writer.write(lineSeparator);
start = off + 1;
}
}
if (start != off)
writer.write(ch, start, off - start);
}
}
private Writer writer;
private boolean keepOpen;
private final char[] chBuf = new char[1];
private final String lineSeparator = System.getProperty("line.separator");
private String[] escapes = new String[128];
private final EscapeCharacterHandler escapeCharacterHandler = new EscapeCharacterHandler();
private final CharacterHandler ignoreCharacterHandler = new CharacterHandler();
private final CharacterHandler dataCharacterHandler = new DataCharacterHandler();
private CharacterHandler controlCharacterHandler;
private CharacterHandler characterHandler;
private int depth = 0;
private CharacterHandler[] characterHandlers = new CharacterHandler[1];
public NXMLOutputHandler() {
characterHandler = ignoreCharacterHandler;
if (!lineSeparator.equals("\n")) {
escapes['\n'] = lineSeparator;
controlCharacterHandler = new LineControlCharacterHandler();
}
else
controlCharacterHandler = new ControlCharacterHandler();
}
public DocumentHandler init(Destination dest, AttributeList atts) throws IOException {
String mediaType = atts.getValue("media-type");
if (mediaType == null)
mediaType = "text/plain";
writer = new BufferedWriter(dest.getWriter(mediaType,
atts.getValue("encoding")));
keepOpen = dest.keepOpen();
return this;
}
public void startDocument() { }
public void characters(char[] ch, int off, int len) throws SAXException {
try {
characterHandler.characters(ch, off, len);
}
catch (IOException e) {
throw new SAXException(e);
}
}
public void ignorableWhitespace(char[] ch, int off, int len) throws SAXException {
characters(ch, off, len);
}
public void startElement(String name, AttributeList atts) throws SAXException {
if (name.equals("control"))
push(controlCharacterHandler);
else if (name.equals("data"))
push(dataCharacterHandler);
else if (name.equals("escape")) {
escapeCharacterHandler.setChar(atts.getValue("char"));
push(escapeCharacterHandler);
}
else if (name.equals("char")) {
String num = atts.getValue("number");
if (num != null) {
try {
int c = Integer.parseInt(num);
if (c >= 0 && c < 65536) {
chBuf[0] = (char)c;
characters(chBuf, 0, 1);
}
}
catch (NumberFormatException e) { }
}
}
}
public void endElement(String name) throws SAXException {
if (name.equals("control") || name.equals("data"))
pop();
else if (name.equals("escape")) {
escapeCharacterHandler.endChar();
pop();
}
}
public void pop() {
characterHandler = characterHandlers[--depth];
}
public void push(CharacterHandler handler) {
if (depth >= characterHandlers.length) {
CharacterHandler[] oldHandlers = characterHandlers;
characterHandlers = new CharacterHandler[oldHandlers.length * 2];
System.arraycopy(oldHandlers, 0, characterHandlers, 0, oldHandlers.length);
}
characterHandlers[depth++] = characterHandler;
characterHandler = handler;
}
public void processingInstruction(String target, String data) { }
public void endDocument() throws SAXException {
try {
if (writer != null) {
if (keepOpen)
writer.flush();
else
writer.close();
writer = null;
}
}
catch (IOException e) {
throw new SAXException(e);
}
}
public void setDocumentLocator(org.xml.sax.Locator loc) { }
}
|