package org.jivesoftware.util;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.tree.NamespaceStack;
import org.xml.sax.*;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.XMLFilterImpl;
import java.io.*;
import java.util.*;
/**
* Replacement class of the original XMLWriter.java (version: 1.77) since the original is still
* using StringBuffer which is not fast.
*/
public class XMLWriter extends XMLFilterImpl implements LexicalHandler {
private static final String PAD_TEXT = " ";
protected static final String[] LEXICAL_HANDLER_NAMES = {
"http://xml.org/sax/properties/lexical-handler",
"http://xml.org/sax/handlers/LexicalHandler"
};
protected static final OutputFormat DEFAULT_FORMAT = new OutputFormat();
/** Should entityRefs by resolved when writing ? */
private boolean resolveEntityRefs = true;
/** Stores the last type of node written so algorithms can refer to the
* previous node type */
protected int lastOutputNodeType;
/** Stores the xml:space attribute value of preserve for whitespace flag */
protected boolean preserve=false;
/** The Writer used to output to */
protected Writer writer;
/** The Stack of namespaceStack written so far */
private NamespaceStack namespaceStack = new NamespaceStack();
/** The format used by this writer */
private OutputFormat format;
/** whether we should escape text */
private boolean escapeText = true;
/** The initial number of indentations (so you can print a whole
document indented, if you like) **/
private int indentLevel = 0;
/** buffer used when escaping strings */
private StringBuilder buffer = new StringBuilder();
/** whether we have added characters before from the same chunk of characters */
private boolean charactersAdded = false;
private char lastChar;
/** Whether a flush should occur after writing a document */
private boolean autoFlush;
/** Lexical handler we should delegate to */
private LexicalHandler lexicalHandler;
/** Whether comments should appear inside DTD declarations - defaults to false */
private boolean showCommentsInDTDs;
/** Is the writer curerntly inside a DTD definition? */
private boolean inDTD;
/** The namespaces used for the current element when consuming SAX events */
private Map namespacesMap;
/**
* what is the maximum allowed character code
* such as 127 in US-ASCII (7 bit) or 255 in ISO-* (8 bit)
* or -1 to not escape any characters (other than the special XML characters like < > &)
*/
private int maximumAllowedCharacter;
public XMLWriter(Writer writer) {
this( writer, DEFAULT_FORMAT );
}
public XMLWriter(Writer writer, OutputFormat format) {
this.writer = writer;
this.format = format;
namespaceStack.push(Namespace.NO_NAMESPACE);
}
public XMLWriter() throws UnsupportedEncodingException {
this.format = DEFAULT_FORMAT;
this.writer = new BufferedWriter( new OutputStreamWriter( System.out, "UTF-8" ) );
this.autoFlush = true;
namespaceStack.push(Namespace.NO_NAMESPACE);
}
public XMLWriter(OutputStream out) throws UnsupportedEncodingException {
this.format = DEFAULT_FORMAT;
this.writer = createWriter(out, format.getEncoding());
this.autoFlush = true;
namespaceStack.push(Namespace.NO_NAMESPACE);
}
public XMLWriter(OutputStream out, OutputFormat format) throws UnsupportedEncodingException {
this.format = format;
this.writer = createWriter(out, format.getEncoding());
this.autoFlush = true;
namespaceStack.push(Namespace.NO_NAMESPACE);
}
public XMLWriter(OutputFormat format) throws UnsupportedEncodingException {
this.format = format;
this.writer = createWriter( System.out, format.getEncoding() );
this.autoFlush = true;
namespaceStack.push(Namespace.NO_NAMESPACE);
}
public void setWriter(Writer writer) {
this.writer = writer;
this.autoFlush = false;
}
public void setOutputStream(OutputStream out) throws UnsupportedEncodingException {
this.writer = createWriter(out, format.getEncoding());
this.autoFlush = true;
}
/**
* @return true if text thats output should be escaped.
* This is enabled by default. It could be disabled if
* the output format is textual, like in XSLT where we can have
* xml, html or text output.
*/
public boolean isEscapeText() {
return escapeText;
}
/**
* Sets whether text output should be escaped or not.
* This is enabled by default. It could be disabled if
* the output format is textual, like in XSLT where we can have
* xml, html or text output.
*/
public void setEscapeText(boolean escapeText) {
this.escapeText = escapeText;
}
/** Set the initial indentation level. This can be used to output
* a document (or, more likely, an element) starting at a given
* indent level, so it's not always flush against the left margin.
* Default: 0
*
* @param indentLevel the number of indents to start with
*/
public void setIndentLevel(int indentLevel) {
this.indentLevel = indentLevel;
}
/**
* Returns the maximum allowed character code that should be allowed
* unescaped which defaults to 127 in US-ASCII (7 bit) or
* 255 in ISO-* (8 bit).
*/
public int getMaximumAllowedCharacter() {
if (maximumAllowedCharacter == 0) {
maximumAllowedCharacter = defaultMaximumAllowedCharacter();
}
return maximumAllowedCharacter;
}
/**
* Sets the maximum allowed character code that should be allowed
* unescaped
* such as 127 in US-ASCII (7 bit) or 255 in ISO-* (8 bit)
* or -1 to not escape any characters (other than the special XML characters like < > &)
*
* If this is not explicitly set then it is defaulted from the encoding.
*
* @param maximumAllowedCharacter The maximumAllowedCharacter to set
*/
public void setMaximumAllowedCharacter(int maximumAllowedCharacter) {
this.maximumAllowedCharacter = maximumAllowedCharacter;
}
/** Flushes the underlying Writer */
public void flush() throws IOException {
writer.flush();
}
/** Closes the underlying Writer */
public void close() throws IOException {
writer.close();
}
/** Writes the new line text to the underlying Writer */
public void println() throws IOException {
writer.write( format.getLineSeparator() );
}
/** Writes the given {@link org.dom4j.Attribute}.
*
* @param attribute <code>Attribute</code> to output.
*/
public void write(Attribute attribute) throws IOException {
writeAttribute(attribute);
if ( autoFlush ) {
flush();
}
}
/** <p>This will print the <code>Document</code> to the current Writer.</p>
*
* <p> Warning: using your own Writer may cause the writer's
* preferred character encoding to be ignored. If you use
* encodings other than UTF8, we recommend using the method that
* takes an OutputStream instead. </p>
*
* <p>Note: as with all Writers, you may need to flush() yours
* after this method returns.</p>
*
* @param doc <code>Document</code> to format.
* @throws IOException - if there's any problem writing.
**/
public void write(Document doc) throws IOException {
writeDeclaration();
if (doc.getDocType() != null) {
indent();
writeDocType(doc.getDocType());
}
for ( int i = 0, size = doc.nodeCount(); i < size; i++ ) {
Node node = doc.node(i);
writeNode( node );
}
writePrintln();
if ( au
- 1
- 2
- 3
前往页