sboag 99/12/12 23:35:49
Modified: src/org/apache/xalan/xpath/xml FormatterToHTML.java
FormatterToXML.java
Log:
Major work for performance tuning, better whitespace handling.
Revision Changes Path
1.9 +569 -474
xml-xalan/src/org/apache/xalan/xpath/xml/FormatterToHTML.java
Index: FormatterToHTML.java
===================================================================
RCS file:
/home/cvs/xml-xalan/src/org/apache/xalan/xpath/xml/FormatterToHTML.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- FormatterToHTML.java 1999/12/10 18:42:29 1.8
+++ FormatterToHTML.java 1999/12/13 07:35:49 1.9
@@ -68,15 +68,26 @@
*/
public class FormatterToHTML extends FormatterToXML
{
- static Hashtable s_empties;
- static Hashtable s_attrempties;
- static Hashtable s_attruris;
- static Hashtable s_escapetb;
- static Hashtable s_nonblockelems;
- static Hashtable s_nonblockparents;
-
- Stack m_parents = new Stack();
+ static char[] s_escapetb = {'%', '<', '>', '{', '}', '[', ']', '|', '^',
'"' /* , ' ', '#' '\\', '\'' */};
+
+ /**
+ * Tell if the character should be escaped in a URL attribute.
+ */
+ boolean isURLEscapeChar(char c)
+ {
+ int n = s_escapetb.length;
+ for(int i = 0; i < n; i++)
+ {
+ if(s_escapetb[i] == c)
+ return true;
+ }
+ return false;
+ }
+ StringVector m_parents = new StringVector();
+ BoolStack m_isRawStack = new BoolStack();
+ boolean m_inBlockElem = false;
+
static String[] s_HTMLlat1 =
{
"nbsp", "iexcl", "cent", "pound",
@@ -141,92 +152,187 @@
// "lceil", "rceil", "lfloor",
"rfloor",
// "lang", "rang", "loz",
"spades",
// "clubs", "hearts", "diams"};
+
+ static Hashtable m_elementFlags = new Hashtable();
+
static
{
- s_empties = new Hashtable();
- // HTML 4.0 strict DTD
- s_empties.put("AREA", "AREA");
- s_empties.put("BASE", "BASE");
- s_empties.put("BR", "BR");
- s_empties.put("COL", "COL");
- s_empties.put("HR", "HR");
- s_empties.put("IMG", "IMG");
- s_empties.put("INPUT", "INPUT");
- s_empties.put("LINK", "LINK");
- s_empties.put("META", "META");
- s_empties.put("PARAM", "PARAM");
// HTML 4.0 loose DTD
- s_empties.put("BASEFONT", "BASEFONT");
- s_empties.put("FRAME", "FRAME");
- s_empties.put("ISINDEX", "ISINDEX");
-
- s_nonblockparents = new Hashtable();
- s_nonblockparents.put("P", "P");
- s_nonblockparents.put("SPAN", "SPAN");
-
- s_nonblockelems = new Hashtable();
- s_nonblockelems.put("FONT", "FONT");
- s_nonblockelems.put("A", "A");
- s_nonblockelems.put("TD", "TD");
- s_nonblockelems.put("IMG", "IMG");
- s_nonblockelems.put("B", "B");
- s_nonblockelems.put("I", "I");
- // s_nonblockelems.put("SPAN", "SPAN");
-
- s_attrempties = new Hashtable();
+ m_elementFlags.put("BASEFONT", new ElemDesc(0|ElemDesc.EMPTY));
+ m_elementFlags.put("FRAME", new
ElemDesc(0|ElemDesc.EMPTY|ElemDesc.BLOCK));
+ m_elementFlags.put("FRAMESET", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("NOFRAMES", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("ISINDEX", new
ElemDesc(0|ElemDesc.EMPTY|ElemDesc.BLOCK));
+ m_elementFlags.put("APPLET", new
ElemDesc(0|ElemDesc.WHITESPACESENSITIVE));
+ m_elementFlags.put("CENTER", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("DIR", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("MENU", new ElemDesc(0|ElemDesc.BLOCK));
+
// HTML 4.0 strict DTD
- s_attrempties.put("checked", "checked");
- s_attrempties.put("disabled", "disabled");
- s_attrempties.put("readonly", "readonly");
- s_attrempties.put("multiple", "multiple");
- s_attrempties.put("disabled", "disabled");
- s_attrempties.put("selected", "selected");
-
- s_attruris = new Hashtable(); // used to catch URI attributes
- String[] URLAttrsHREFSingle = {"href"};
- String[] URLAttrsCITESingle = {"cite"};
- s_attruris.put("base", URLAttrsHREFSingle);
- s_attruris.put("link", URLAttrsHREFSingle);
- s_attruris.put("area", URLAttrsHREFSingle);
- // From the HTML 4.0 spec: Note. The same conversion based on UTF-8
- // should be applied to values of the name attribute for the A element.
- String[] URLAttrs_A = {"href", "name"};
- s_attruris.put("a", URLAttrs_A);
- String[] URLAttrs_INPUT = {"src", "usemap"};
- s_attruris.put("input", URLAttrs_INPUT);
- String[] URLAttrs_SCRIPT = {"src", "for"};
- s_attruris.put("script", URLAttrs_SCRIPT);
- String[] URLAttrs_IMG = {"src", "longdesc", "usemap"};
- s_attruris.put("img", URLAttrs_IMG);
- String[] URLAttrs_OBJECT = {"classid", "codebase", "data", "archive",
"usemap"};
- s_attruris.put("object", URLAttrs_OBJECT);
- s_attruris.put("q", URLAttrsCITESingle);
- s_attruris.put("blockquote", URLAttrsCITESingle);
- s_attruris.put("ins", URLAttrsCITESingle);
- s_attruris.put("del", URLAttrsCITESingle);
- String[] URLAttrs_FORM = {"action"};
- s_attruris.put("form", URLAttrs_FORM);
- String[] URLAttrs_HEAD = {"profile"};
- s_attruris.put("head", URLAttrs_HEAD);
+ m_elementFlags.put("TT", new ElemDesc(0|ElemDesc.FONTSTYLE));
+ m_elementFlags.put("I", new ElemDesc(0|ElemDesc.FONTSTYLE));
+ m_elementFlags.put("B", new ElemDesc(0|ElemDesc.FONTSTYLE));
+ m_elementFlags.put("BIG", new ElemDesc(0|ElemDesc.FONTSTYLE));
+ m_elementFlags.put("SMALL", new ElemDesc(0|ElemDesc.FONTSTYLE));
+ m_elementFlags.put("EM", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("STRONG", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("DFN", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("CODE", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("SAMP", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("KBD", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("VAR", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("CITE", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("ABBR", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("ACRONYM", new ElemDesc(0|ElemDesc.PHRASE));
+ m_elementFlags.put("SUP", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL));
+ m_elementFlags.put("SUB", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL));
+ m_elementFlags.put("SPAN", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL));
+ m_elementFlags.put("BDO", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL));
+ m_elementFlags.put("BR", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL|ElemDesc.EMPTY|ElemDesc.BLOCK));
+ m_elementFlags.put("BODY", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("ADDRESS", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM|ElemDesc.BLOCKFORMFIELDSET));
+ m_elementFlags.put("DIV", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM|ElemDesc.BLOCKFORMFIELDSET));
+ m_elementFlags.put("A", new ElemDesc(0|ElemDesc.SPECIAL));
+ m_elementFlags.put("MAP", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL|ElemDesc.BLOCK));
+ m_elementFlags.put("AREA", new
ElemDesc(0|ElemDesc.EMPTY|ElemDesc.BLOCK));
+ m_elementFlags.put("LINK", new
ElemDesc(0|ElemDesc.HEADMISC|ElemDesc.EMPTY|ElemDesc.BLOCK));
+ m_elementFlags.put("IMG", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL|ElemDesc.EMPTY|ElemDesc.WHITESPACESENSITIVE));
+ m_elementFlags.put("OBJECT", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL|ElemDesc.HEADMISC|ElemDesc.WHITESPACESENSITIVE));
+ m_elementFlags.put("PARAM", new ElemDesc(0|ElemDesc.EMPTY));
+ m_elementFlags.put("HR", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM|ElemDesc.BLOCKFORMFIELDSET|ElemDesc.EMPTY));
+ m_elementFlags.put("P", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM|ElemDesc.BLOCKFORMFIELDSET));
+ m_elementFlags.put("H1", new ElemDesc(0|ElemDesc.HEAD|ElemDesc.BLOCK));
+ m_elementFlags.put("H2", new ElemDesc(0|ElemDesc.HEAD|ElemDesc.BLOCK));
+ m_elementFlags.put("H3", new ElemDesc(0|ElemDesc.HEAD|ElemDesc.BLOCK));
+ m_elementFlags.put("H4", new ElemDesc(0|ElemDesc.HEAD|ElemDesc.BLOCK));
+ m_elementFlags.put("H5", new ElemDesc(0|ElemDesc.HEAD|ElemDesc.BLOCK));
+ m_elementFlags.put("H6", new ElemDesc(0|ElemDesc.HEAD|ElemDesc.BLOCK));
+ m_elementFlags.put("PRE", new
ElemDesc(0|ElemDesc.PREFORMATTED|ElemDesc.BLOCK));
+ m_elementFlags.put("Q", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL));
+ m_elementFlags.put("BLOCKQUOTE", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM|ElemDesc.BLOCKFORMFIELDSET));
+ m_elementFlags.put("INS", new ElemDesc(0));
+ m_elementFlags.put("DEL", new ElemDesc(0));
+ m_elementFlags.put("DL", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM|ElemDesc.BLOCKFORMFIELDSET));
+ m_elementFlags.put("DT", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("DD", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("OL", new ElemDesc(0|ElemDesc.LIST|ElemDesc.BLOCK));
+ m_elementFlags.put("UL", new ElemDesc(0|ElemDesc.LIST|ElemDesc.BLOCK));
+ m_elementFlags.put("LI", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("FORM", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("LABEL", new ElemDesc(0|ElemDesc.FORMCTRL));
+ m_elementFlags.put("INPUT", new
ElemDesc(0|ElemDesc.FORMCTRL|ElemDesc.INLINELABEL|ElemDesc.EMPTY));
+ m_elementFlags.put("SELECT", new
ElemDesc(0|ElemDesc.FORMCTRL|ElemDesc.INLINELABEL));
+ m_elementFlags.put("OPTGROUP", new ElemDesc(0));
+ m_elementFlags.put("OPTION", new ElemDesc(0));
+ m_elementFlags.put("TEXTAREA", new
ElemDesc(0|ElemDesc.FORMCTRL|ElemDesc.INLINELABEL));
+ m_elementFlags.put("FIELDSET", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM));
+ m_elementFlags.put("LEGEND", new ElemDesc(0));
+ m_elementFlags.put("BUTTON", new
ElemDesc(0|ElemDesc.FORMCTRL|ElemDesc.INLINELABEL));
+ m_elementFlags.put("TABLE", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM|ElemDesc.BLOCKFORMFIELDSET));
+ m_elementFlags.put("CAPTION", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("THEAD", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("TFOOT", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("TBODY", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("COLGROUP", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("COL", new ElemDesc(0|ElemDesc.EMPTY|ElemDesc.BLOCK));
+ m_elementFlags.put("TR", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("TH", new ElemDesc(0));
+ m_elementFlags.put("TD", new ElemDesc(0));
+ m_elementFlags.put("HEAD", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("TITLE", new ElemDesc(0|ElemDesc.BLOCK));
+ m_elementFlags.put("BASE", new
ElemDesc(0|ElemDesc.EMPTY|ElemDesc.BLOCK));
+ m_elementFlags.put("META", new
ElemDesc(0|ElemDesc.HEADMISC|ElemDesc.EMPTY|ElemDesc.BLOCK));
+ m_elementFlags.put("STYLE", new
ElemDesc(0|ElemDesc.HEADMISC|ElemDesc.RAW|ElemDesc.BLOCK));
+ m_elementFlags.put("SCRIPT", new
ElemDesc(0|ElemDesc.SPECIAL|ElemDesc.ASPECIAL|ElemDesc.HEADMISC|ElemDesc.RAW));
+ m_elementFlags.put("NOSCRIPT", new
ElemDesc(0|ElemDesc.BLOCK|ElemDesc.BLOCKFORM|ElemDesc.BLOCKFORMFIELDSET));
+ m_elementFlags.put("HTML", new ElemDesc(0|ElemDesc.BLOCK));
+
+ ElemDesc elemDesc;
+ elemDesc = (ElemDesc)m_elementFlags.get("BASE");
+ elemDesc.setAttr("HREF", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("BLOCKQUOTE");
+ elemDesc.setAttr("CITE", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("INS");
+ elemDesc.setAttr("CITE", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("DEL");
+ elemDesc.setAttr("CITE", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("A");
+ elemDesc.setAttr("HREF", ElemDesc.ATTRURL);
+ elemDesc.setAttr("NAME", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("INPUT");
+ elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
+ elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL);
+ elemDesc.setAttr("CHECKED", ElemDesc.ATTREMPTY);
+ elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
+ elemDesc.setAttr("READONLY", ElemDesc.ATTREMPTY);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("SELECT");
+ elemDesc.setAttr("READONLY", ElemDesc.ATTREMPTY);
+ elemDesc.setAttr("MULTIPLE", ElemDesc.ATTREMPTY);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("OPTGROUP");
+ elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("OPTION");
+ elemDesc.setAttr("SELECTED", ElemDesc.ATTREMPTY);
+ elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("TEXTAREA");
+ elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
+ elemDesc.setAttr("READONLY", ElemDesc.ATTREMPTY);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("BUTTON");
+ elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("SCRIPT");
+ elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
+ elemDesc.setAttr("FOR", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("IMG");
+ elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
+ elemDesc.setAttr("LONGDESC", ElemDesc.ATTRURL);
+ elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("OBJECT");
+ elemDesc.setAttr("CLASSID", ElemDesc.ATTRURL);
+ elemDesc.setAttr("CODEBASE", ElemDesc.ATTRURL);
+ elemDesc.setAttr("DATA", ElemDesc.ATTRURL);
+ elemDesc.setAttr("ARCHIVE", ElemDesc.ATTRURL);
+ elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("FORM");
+ elemDesc.setAttr("ACTION", ElemDesc.ATTRURL);
+
+ elemDesc = (ElemDesc)m_elementFlags.get("HEAD");
+ elemDesc.setAttr("PROFILE", ElemDesc.ATTRURL);
- s_escapetb = new Hashtable(); // other chars to escape
- s_escapetb.put("%", "%");
- s_escapetb.put("<", "<");
- s_escapetb.put(">",">");
-// s_escapetb.put(" "," ");
-// s_escapetb.put("#", "#");
- s_escapetb.put("{", "{");
- s_escapetb.put("}", "}");
- s_escapetb.put("[", "[");
- s_escapetb.put("]", "]");
- // s_escapetb.put("\\","\\");
- s_escapetb.put("|", "|");
- s_escapetb.put("^", "^");
- s_escapetb.put("\"", "\"");
-// s_escapetb.put("'", "'");
}
/**
+ * Dummy element for elements not found.
+ */
+ static private ElemDesc m_dummy = new ElemDesc(0);
+
+ /**
+ * Get a description of the given element.
+ */
+ ElemDesc getElemDesc(String name)
+ {
+ if(null != name)
+ {
+ Object obj = m_elementFlags.get(name);
+ if(null != obj)
+ return (ElemDesc)obj;
+ }
+ return m_dummy;
+ }
+
+ /**
* Default constructor.
*/
public FormatterToHTML()
@@ -244,6 +350,56 @@
initEncodings();
}
+ /**
+ * Constructor using a writer.
+ * @param writer The character output stream to use.
+ */
+ public FormatterToHTML(FormatterToXML xmlListener)
+ {
+ super(xmlListener);
+ m_doIndent = true; // TODO: But what if the user wants to set it???
+ }
+
+ /**
+ * Set the attribute characters what will require special mapping.
+ */
+ protected void initAttrCharsMap()
+ {
+ super.initAttrCharsMap();
+ m_attrCharsMap[(int)'\n'] = 'S';
+ m_attrCharsMap[(int)10] = 'S';
+ }
+
+ /**
+ * Set the characters what will require special mapping.
+ */
+ protected void initCharsMap()
+ {
+ initAttrCharsMap();
+ int n = (m_maxCharacter > SPECIALSSIZE) ? SPECIALSSIZE : m_maxCharacter;
+ for(int i = 0; i < n; i++)
+ {
+ m_charsMap[i] = '\0';
+ }
+ m_charsMap[(int)'\n'] = 'S';
+ m_charsMap[(int)'<'] = 'S';
+ m_charsMap[(int)'>'] = 'S';
+ m_charsMap[(int)'&'] = 'S';
+ for(int i = 0; i < 10; i++)
+ {
+ m_charsMap[i] = 'S';
+ }
+ n = (255 > SPECIALSSIZE) ? 255 : SPECIALSSIZE;
+ for(int i = 160; i < n; i++)
+ {
+ m_charsMap[i] = 'S';
+ }
+ for(int i = m_maxCharacter; i < SPECIALSSIZE; i++)
+ {
+ m_charsMap[i] = 'S';
+ }
+ }
+
String m_currentElementName = null;
// protected boolean shouldIndent()
@@ -259,40 +415,47 @@
*/
public void startDocument ()
throws SAXException
- {
+ {
m_needToOutputDocTypeDecl = true;
- m_startNewLine = false;
+ m_startNewLine = false;
+ m_shouldNotWriteXMLHeader = true;
if(true == m_needToOutputDocTypeDecl)
{
- try
+ if((null != m_doctypeSystem) || (null != m_doctypePublic))
{
- if((null != m_doctypeSystem) || (null != m_doctypePublic))
+ accum("<!DOCTYPE HTML ");
+ if(null != m_doctypePublic)
{
- m_writer.write("<!DOCTYPE HTML ");
if(null != m_doctypePublic)
{
- m_writer.write(" PUBLIC \"");
- m_writer.write(m_doctypePublic);
- m_writer.write("\"");
+ accum(" PUBLIC \"");
+ accum(m_doctypePublic);
+ accum("\"");
}
if(null != m_doctypeSystem)
{
if(null == m_doctypePublic)
- m_writer.write(" SYSTEM \"");
+ accum(" SYSTEM \"");
else
- m_writer.write(" \"");
- m_writer.write(m_doctypeSystem);
- m_writer.write("\"");
+ accum(" \"");
+ accum(m_doctypeSystem);
+ accum("\"");
}
- m_writer.write(">");
- m_writer.write(m_lineSep);
+ accum(">");
+ accum(m_lineSep);
}
-
- }
- catch(IOException ioe)
- {
- throw new SAXException("IO error", ioe);
+ if(null != m_doctypeSystem)
+ {
+ if(null == m_doctypePublic)
+ accum(" SYSTEM \"");
+ else
+ accum(" \"");
+ accum(m_doctypeSystem);
+ accum("\"");
+ }
+ accum(">");
+ outputLineSep();
}
}
m_needToOutputDocTypeDecl = false;
@@ -311,55 +474,47 @@
public void startElement (String name, AttributeList atts)
throws SAXException
{
-
boolean savedDoIndent = m_doIndent;
boolean noLineBreak;
- // If the previous element is a non-block element or the next
- // element is a non-block element, then do not indent.
- m_doIndent = ((null != s_nonblockelems.get(name.toUpperCase())) ||
- ((null != m_currentElementName)
- && ((null !=
s_nonblockelems.get(m_currentElementName.toUpperCase()) )
- || (null !=
s_nonblockparents.get(m_currentElementName.toUpperCase()) ))))
- ? false : true;
-
- // m_currentElementName = name.toUpperCase();
- m_currentElementName = name;
- m_parents.push(m_currentElementName.toUpperCase());
- // super.startElement(m_currentElementName, atts);
- try
- {
- writeParentTagEnd();
- m_ispreserve = false;
+
+ writeParentTagEnd();
- // m_doIndent = ( (!m_elemNames.isEmpty()) && (null !=
s_spanelems.get(m_elemNames.peek())))
- // ? false : true;
-
- // System.out.println(name+": m_doIndent = "+m_doIndent+",
m_ispreserve = "+m_ispreserve+", m_isprevtext = "+m_isprevtext);
- if (shouldIndent() && !m_elemStack.isEmpty())
- {
- m_startNewLine = true;
- indent(this.m_writer, m_currentIndent);
- }
+ String nameUpper = name.toUpperCase();
- this.m_writer.write('<');
- this.m_writer.write(name);
-
- int nAttrs = atts.getLength();
- for (int i = 0; i < nAttrs ; i++)
- {
- processAttribute(atts.getName(i), atts.getValue(i));
- }
- // Flag the current element as not yet having any children.
- openElementForChildren();
-
- m_currentIndent += this.indent;
-
- m_isprevtext = false;
+ ElemDesc elemDesc = getElemDesc(nameUpper);
+ // ElemDesc parentElemDesc = getElemDesc(m_currentElementName);
+
+ boolean isBlockElement = elemDesc.is(ElemDesc.BLOCK);
+
+ if(m_ispreserve)
+ m_ispreserve = false;
+ else if(m_doIndent && (null != m_currentElementName) && (!m_inBlockElem
|| isBlockElement))
+ {
+ m_startNewLine = true;
+ indent(m_currentIndent);
}
- catch(IOException ioe)
+
+ m_inBlockElem = !isBlockElement;
+
+ m_isRawStack.push(elemDesc.is(ElemDesc.RAW));
+
+ m_currentElementName = nameUpper;
+ m_parents.push(m_currentElementName);
+
+ this.accum('<');
+ this.accum(name);
+
+ int nAttrs = atts.getLength();
+ for (int i = 0; i < nAttrs ; i++)
{
- throw new SAXException("IO error", ioe);
+ processAttribute(atts.getName(i), elemDesc, atts.getValue(i));
}
+ // Flag the current element as not yet having any children.
+ openElementForChildren();
+
+ m_currentIndent += this.indent;
+
+ m_isprevtext = false;
m_doIndent = savedDoIndent;
}
@@ -374,54 +529,72 @@
public void endElement (String name)
throws SAXException
{
- try
+ m_currentIndent -= this.indent;
+ // name = name.toUpperCase();
+ boolean hasChildNodes = childNodesWereAdded();
+ // System.out.println(m_currentElementName);
+ m_parents.pop();
+ m_isRawStack.pop();
+
+ String nameUpper = name.toUpperCase();
+
+ ElemDesc elemDesc = getElemDesc(nameUpper);
+ // ElemDesc parentElemDesc = getElemDesc(m_currentElementName);
+
+ boolean isBlockElement = elemDesc.is(ElemDesc.BLOCK);
+
+ boolean shouldIndent = false;
+ if(m_ispreserve)
{
- m_currentIndent -= this.indent;
- // name = name.toUpperCase();
- boolean hasChildNodes = childNodesWereAdded();
- // System.out.println(m_currentElementName);
- m_parents.pop();
- boolean isWhitespaceSensitive
- = (null != s_nonblockelems.get(name.toUpperCase())) ||
- (null != s_nonblockelems.get(m_currentElementName.toUpperCase()))
||
- (!m_parents.isEmpty() && (null !=
s_nonblockparents.get(m_parents.peek()) ));
-
- if (hasChildNodes)
+ m_ispreserve = false;
+ }
+ else if(m_doIndent && (!m_inBlockElem || isBlockElement))
+ {
+ m_startNewLine = true;
+ shouldIndent = true;
+ // indent(m_currentIndent);
+ }
+
+ m_inBlockElem = !isBlockElement;
+
+ if (hasChildNodes)
+ {
+ if (shouldIndent)
+ indent(m_currentIndent);
+ this.accum("</");
+ this.accum(name);
+ this.accum('>');
+ m_currentElementName = name;
+ }
+ else
+ {
+ if(!elemDesc.is(ElemDesc.EMPTY))
{
- if (shouldIndent() && !isWhitespaceSensitive)
- indent(this.m_writer, m_currentIndent);
- this.m_writer.write("</");
- this.m_writer.write(name);
- this.m_writer.write('>');
- m_currentElementName = name;
+ this.accum('>');
+ if (shouldIndent)
+ indent(m_currentIndent);
+ this.accum('<');
+ this.accum('/');
+ this.accum(name);
+ this.accum('>');
}
else
{
- if(s_empties.get(name.toUpperCase()) == null)
- {
- this.m_writer.write(">");
- // if (shouldIndent() && !isWhitespaceSensitive)
- // indent(this.m_writer, m_currentIndent);
- this.m_writer.write("</");
- this.m_writer.write(name);
- this.m_writer.write('>');
- }
- else
- {
- this.m_writer.write('>');
- }
- }
- if (hasChildNodes)
- {
- m_ispreserve = ((Boolean)m_preserves.pop()).booleanValue();
+ this.accum('>');
}
- m_isprevtext = false;
- // m_elemNames.pop();
}
- catch(IOException ioe)
+
+ if (elemDesc.is(ElemDesc.WHITESPACESENSITIVE))
+ m_ispreserve = true;
+
+ /*
+ if (hasChildNodes)
{
- throw new SAXException("IO error", ioe);
+ m_ispreserve = m_preserves.pop();
}
+ */
+ m_isprevtext = false;
+ // m_elemNames.pop();
}
/**
@@ -429,95 +602,52 @@
* @param name The name of the attribute.
* @param value The value of the attribute.
*/
- protected void processAttribute(String name, String value)
+ protected void processAttribute(String name, ElemDesc elemDesc, String
value)
throws SAXException
{
- try
+ String nameUpper = name.toUpperCase();
+ this.accum(' ');
+ if(elemDesc.isAttrFlagSet(nameUpper, ElemDesc.ATTREMPTY) &&
+ (value.length() == 0) || value.equalsIgnoreCase(name))
{
- // String aname = name.toLowerCase();
- String aname = name;
- if(!aname.equals("xmlns") && !aname.startsWith("xmlns:"))
- {
- String pval = null;
- if (aname.equals("xml:lang")) aname = "lang";
- // qualify with an element??
- String val[] =
(String[])(s_attruris.get(m_currentElementName.toLowerCase()));
- if(val != null)
- {
- int nAttrs = val.length;
- int i;
- String lowername = aname.toLowerCase();
- for(i = 0; i < nAttrs; i++)
- {
- if(val[i].equals(lowername))
- {
- pval = prepAttrURI(value, m_attrSpecialChars, this.m_encoding);
- break;
- }
- }
- if(i == nAttrs)
- {
- pval = prepAttrString(value, m_attrSpecialChars,
this.m_encoding);
- }
- }
- else
- {
- pval = prepAttrString(value, m_attrSpecialChars, this.m_encoding);
- }
- if(s_attrempties.get(aname.toLowerCase()) == null)
- {
- this.m_writer.write(' ');
- this.m_writer.write(aname);
- this.m_writer.write("=\"");
- this.m_writer.write(pval);
- this.m_writer.write('\"');
- }
- else
- {
- this.m_writer.write(' ');
- if((pval.length() == 0) || pval.equalsIgnoreCase(aname))
- {
- this.m_writer.write(aname);
- }
- else
- {
- this.m_writer.write(aname);
- this.m_writer.write("=\"");
- this.m_writer.write(pval);
- this.m_writer.write('\"');
- }
- }
- }
+ this.accum(name);
}
- catch(IOException ioe)
+ else
{
- throw new SAXException("IO error", ioe);
+ this.accum(name);
+ this.accum('=');
+ this.accum('\"');
+ if(elemDesc.isAttrFlagSet(nameUpper, ElemDesc.ATTRURL))
+ writeAttrURI(value, this.m_encoding);
+ else
+ writeAttrString(value, this.m_encoding);
+ this.accum('\"');
}
}
/**
- * Returns the specified <var>string</var> after substituting non ASCII
characters,
+ * Write the specified <var>string</var> after substituting non ASCII
characters,
* with <CODE>%HH</CODE>, where HH is the hex of the byte value.
*
* @param string String to convert to XML format.
* @param specials Chracters, should be represeted in chracter
referenfces.
* @param encoding CURRENTLY NOT IMPLEMENTED.
- * @return XML-formatted string.
* @see #backReference
*/
- public String prepAttrURI(String string, String specials, String encoding)
+ public void writeAttrURI(String string, String encoding)
throws SAXException
{
- StringBuffer sb = new StringBuffer(string.length()*10);
+ char[] stringArray = string.toCharArray();
+ int len = stringArray.length;
- for (int i = 0; i < string.length(); i ++)
+ for (int i = 0; i < len; i ++)
{
- char ch = string.charAt(i);
+ char ch = stringArray[i];
if(((ch > 0x1F) && // X'00 - 1F' not valid
(ch < 0x7F)) && // X'7F' not valid
- (s_escapetb.get(String.valueOf(ch))== null) ) // characters in the
table
+ !isURLEscapeChar(ch) ) // characters in the table
{
- sb.append(ch); // valid character, append it
+ accum(ch); // valid character, append it
}
else
{
@@ -529,133 +659,124 @@
// if first 8 bytes are 0, no need to append them.
if (b1 != 0)
{
- sb.append("%");
- sb.append(Integer.toHexString(b1));
+ accum("%");
+ accum(Integer.toHexString(b1));
}
- sb.append("%");
- sb.append(Integer.toHexString(b2));
+ accum("%");
+ accum(Integer.toHexString(b2));
}
}
- return sb.toString();
}
/**
- * Returns the specified <var>string</var> after substituting
<VAR>specials</VAR>,
+ * Writes the specified <var>string</var> after substituting
<VAR>specials</VAR>,
* and UTF-16 surrogates for chracter references <CODE>&#xnn</CODE>.
*
* @param string String to convert to XML format.
* @param specials Chracters, should be represeted in chracter
referenfces.
* @param encoding CURRENTLY NOT IMPLEMENTED.
- * @return XML-formatted string.
* @see #backReference
*/
- public String prepAttrString(String string, String specials, String
encoding)
+ public void writeAttrString(String string, String encoding)
throws SAXException
{
- StringBuffer sb = new StringBuffer(string.length()*12/10);
int strLen = string.length();
- for (int i = 0; i < strLen; i ++)
+ // char chars[] = string.toCharArray();
+ for (int i = 0; i < strLen; i ++)
{
+ // char ch = chars[i];
char ch = string.charAt(i);
- if(('&' == ch) && ((i+1) < string.length()) && ('{' ==
string.charAt(i+1)))
+ if((ch < SPECIALSSIZE) && (m_attrCharsMap[ch] != 'S'))
+ {
+ accum(ch);
+ }
+ else if(('&' == ch) && ((i+1) < strLen) && ('{' == string.charAt(i+1)))
{
- sb.append(ch); // no escaping in this case, as specified in 15.2
+ accum(ch); // no escaping in this case, as specified in 15.2
}
- else
+ else if (0xd800 <= ch && ch < 0xdc00)
{
- int chNum = (int)ch;
- int index = specials.indexOf(chNum);
- if ((index >= 0) || (chNum > m_maxCharacter))
+ // UTF-16 surrogate
+ int next;
+ if (i+1 >= string.length())
{
- /*
- if ('<' == ch)
- {
- sb.append("<");
- }
- else if ('>' == ch)
- {
- sb.append(">");
- }
- else
- */
- if ('&' == ch)
- {
- sb.append("&");
- }
- else if ('"' == ch)
- {
- sb.append(""");
- }
- else if((chNum >= 9) && (chNum <= 126))
- {
- sb.append(ch);
- }
- else if((chNum >= 160) && (chNum <= 255))
- {
- sb.append("&");
- sb.append(s_HTMLlat1[((int)ch)-160]);
- sb.append(";");
- }
- else if((chNum >= 913) && (chNum <= 982))
- {
- sb.append("&");
- sb.append(HTMLsymbol1[((int)ch)-913]);
- sb.append(";");
- }
- else if (402 == ch)
- {
- sb.append("ƒ");
- }
- else
- {
- sb.append("&#x");
- sb.append(Integer.toHexString(chNum));
- sb.append(";");
- }
+ throw new SAXException("Invalid UTF-16 surrogate detected: "
+ +Integer.toHexString(ch)+ " ?");
}
- else if (0xd800 <= chNum && chNum < 0xdc00)
+ else
{
- // UTF-16 surrogate
- int next;
- if (i+1 >= string.length())
- {
+ next = string.charAt(++i);
+ if (!(0xdc00 <= next && next < 0xe000))
throw new SAXException("Invalid UTF-16 surrogate detected: "
- +Integer.toHexString(ch)+ " ?");
- }
- else
- {
- next = string.charAt(++i);
- if (!(0xdc00 <= next && next < 0xe000))
- throw new SAXException("Invalid UTF-16 surrogate detected: "
- +Integer.toHexString(ch)+" "+Integer.toHexString(next));
- next = ((ch-0xd800)<<10)+next-0xdc00+0x00010000;
- }
- sb.append("&#x");
- sb.append(Integer.toHexString(next));
- sb.append(";");
- /*} else if (null != ctbc && !ctbc.canConvert(ch)) {
- sb.append("&#x");
- sb.append(Integer.toString((int)ch, 16));
- sb.append(";");*/
+ +Integer.toHexString(ch)+" "+Integer.toHexString(next));
+ next = ((ch-0xd800)<<10)+next-0xdc00+0x00010000;
}
- else
+ accum("&#x");
+ accum(Integer.toHexString(next));
+ accum(";");
+ /*} else if (null != ctbc && !ctbc.canConvert(ch)) {
+ accum("&#x");
+ accum(Integer.toString((int)ch, 16));
+ accum(";");*/
+ }
+ else
+ {
+ if ('\n' == ch)
+ {
+ outputLineSep();
+ }
+ else if (10 == ch)
+ {
+ outputLineSep();
+ }
+ else if ('&' == ch)
+ {
+ accum("&");
+ }
+ else if ('"' == ch)
{
- sb.append(ch);
+ accum(""");
}
+ else if((ch >= 9) && (ch <= 126))
+ {
+ accum(ch);
+ }
+ else if((ch >= 160) && (ch <= 255))
+ {
+ accum("&");
+ accum(s_HTMLlat1[((int)ch)-160]);
+ accum(";");
+ }
+ else if((ch >= 913) && (ch <= 982))
+ {
+ accum("&");
+ accum(HTMLsymbol1[((int)ch)-913]);
+ accum(";");
+ }
+ else if (402 == ch)
+ {
+ accum("ƒ");
+ }
+ else
+ {
+ accum("&#x");
+ accum(Integer.toHexString(ch));
+ accum(";");
+ }
}
}
- return sb.toString();
}
private int copyEntityIntoBuf(String s, int pos)
+ throws SAXException
{
int l = s.length();
- m_charBuf[pos++] = '&';
+ accum('&');
for(int i= 0; i < l; i++)
{
- m_charBuf[pos++] = s.charAt(i);
+ accum(s.charAt(i));
}
- m_charBuf[pos++] = ';';
+ accum(';');
return pos;
}
@@ -702,20 +823,18 @@
return;
}
- if((null != m_currentElementName) &&
- (m_currentElementName.equalsIgnoreCase("SCRIPT") ||
- m_currentElementName.equalsIgnoreCase("STYLE")))
+ if(m_isRawStack.peek())
{
try
{
writeParentTagEnd();
m_ispreserve = true;
if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
- // this.m_writer.write("<![CDATA[");
- // this.m_writer.write(chars, start, length);
+ indent(m_currentIndent);
+ // this.accum("<![CDATA[");
+ // this.accum(chars, start, length);
writeNormalizedChars(chars, start, length, false);
- // this.m_writer.write("]]>");
+ // this.accum("]]>");
return;
}
catch(IOException ioe)
@@ -724,109 +843,98 @@
}
}
- try
+ writeParentTagEnd();
+ m_ispreserve = true;
+ int pos = 0;
+ int end = start+length;
+ for (int i = start; i < end; i ++)
{
- writeParentTagEnd();
- m_ispreserve = true;
- int pos = 0;
- int end = start+length;
- for (int i = start; i < end; i ++)
+ char ch = chars[i];
+
+ if((ch < SPECIALSSIZE) && (m_charsMap[ch] != 'S'))
{
- char ch = chars[i];
- int chNum = (int)ch;
- if ('\n' == ch)
- {
- for(int k = 0; k < m_lineSepLen; k++)
- {
- m_charBuf[pos++] = m_lineSep.charAt(k);
- }
- }
- else if ('<' == ch)
- {
- pos = copyEntityIntoBuf("lt", pos);
- }
- else if ('>' == ch)
- {
- pos = copyEntityIntoBuf("gt", pos);
- }
- else if ('&' == ch)
- {
- pos = copyEntityIntoBuf("amp", pos);
- }
- else if((chNum >= 9) && (chNum <= 126))
- {
- m_charBuf[pos++] = ch;
- }
- else if((chNum >= 160) && (chNum <= 255))
- {
- pos = copyEntityIntoBuf(s_HTMLlat1[((int)ch)-160], pos);
- }
- else if((chNum >= 913) && (chNum <= 982))
- {
- pos = copyEntityIntoBuf(HTMLsymbol1[((int)ch)-913], pos);
- }
- else if (402 == ch)
+ accum(ch);
+ continue;
+ }
+
+ if ('\n' == ch)
+ {
+ outputLineSep();
+ }
+ else if ('<' == ch)
+ {
+ pos = copyEntityIntoBuf("lt", pos);
+ }
+ else if ('>' == ch)
+ {
+ pos = copyEntityIntoBuf("gt", pos);
+ }
+ else if ('&' == ch)
+ {
+ pos = copyEntityIntoBuf("amp", pos);
+ }
+ else if((ch >= 9) && (ch <= 126))
+ {
+ accum(ch);
+ }
+ else if((ch >= 160) && (ch <= 255))
+ {
+ pos = copyEntityIntoBuf(s_HTMLlat1[((int)ch)-160], pos);
+ }
+ else if((ch >= 913) && (ch <= 982))
+ {
+ pos = copyEntityIntoBuf(HTMLsymbol1[((int)ch)-913], pos);
+ }
+ else if (402 == ch)
+ {
+ pos = copyEntityIntoBuf("fnof", pos);
+ }
+ else if (m_isUTF8 && (0xd800 <= ch && ch < 0xdc00))
+ {
+ // UTF-16 surrogate
+ int next;
+ if (i+1 >= length)
{
- pos = copyEntityIntoBuf("fnof", pos);
+ throw new SAXException("Invalid UTF-16 surrogate detected: "
+ +Integer.toHexString(ch)+ " ?");
}
- else if (m_isUTF8 && (0xd800 <= chNum && chNum < 0xdc00))
+ else
{
- // UTF-16 surrogate
- int next;
- if (i+1 >= length)
- {
+ next = chars[++i];
+ if (!(0xdc00 <= next && next < 0xe000))
throw new SAXException("Invalid UTF-16 surrogate detected: "
- +Integer.toHexString(ch)+ " ?");
- }
- else
- {
- next = chars[++i];
- if (!(0xdc00 <= next && next < 0xe000))
- throw new SAXException("Invalid UTF-16 surrogate detected: "
- +Integer.toHexString(ch)+" "+Integer.toHexString(next));
- next = ((ch-0xd800)<<10)+next-0xdc00+0x00010000;
- }
- m_charBuf[pos++] = '&';
- m_charBuf[pos++] = '#';
- String intStr = Integer.toString(next);
- int nIntStr = intStr.length();
- for(int k = 0; k < nIntStr; k++)
- {
- m_charBuf[pos++] = intStr.charAt(k);
- }
- m_charBuf[pos++] = ';';
- }
- else if((ch >= '\u007F') && (ch <= m_maxCharacter))
- {
- // Hope this is right...
- m_charBuf[pos++] = ch;
+ +Integer.toHexString(ch)+" "+Integer.toHexString(next));
+ next = ((ch-0xd800)<<10)+next-0xdc00+0x00010000;
}
- else
+ accum('&');
+ accum('#');
+ String intStr = Integer.toString(next);
+ int nIntStr = intStr.length();
+ for(int k = 0; k < nIntStr; k++)
{
- m_charBuf[pos++] = '&';
- m_charBuf[pos++] = '#';
- String intStr = Integer.toString(chNum);
- int nIntStr = intStr.length();
- for(int k = 0; k < nIntStr; k++)
- {
- m_charBuf[pos++] = intStr.charAt(k);
- }
- m_charBuf[pos++] = ';';
+ accum(intStr.charAt(k));
}
- // Use 80 as a best guess safe buffer
- if(pos > MAXSAFECHARBUF)
+ accum(';');
+ }
+ else if((ch >= '\u007F') && (ch <= m_maxCharacter))
+ {
+ // Hope this is right...
+ accum(ch);
+ }
+ else
+ {
+ accum('&');
+ accum('#');
+ String intStr = Integer.toString(ch);
+ int nIntStr = intStr.length();
+ for(int k = 0; k < nIntStr; k++)
{
- this.m_writer.write(m_charBuf, 0, pos);
- pos = 0;
+ accum(intStr.charAt(k));
}
+ accum(';');
}
- this.m_writer.write(m_charBuf, 0, pos);
- m_isprevtext = true;
- }
- catch(IOException ioe)
- {
- throw new SAXException("IO error", ioe);
}
+ m_isprevtext = true;
}
/**
@@ -866,8 +974,8 @@
writeParentTagEnd();
m_ispreserve = true;
if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
- // this.m_writer.write(ch, start, length);
+ indent(m_currentIndent);
+ // this.accum(ch, start, length);
writeNormalizedChars(ch, start, length, true);
}
catch(IOException ioe)
@@ -883,10 +991,10 @@
writeParentTagEnd();
m_ispreserve = true;
if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
- // this.m_writer.write("<![CDATA[");
- this.m_writer.write(ch, start, length);
- // this.m_writer.write("]]>");
+ indent(m_currentIndent);
+ // this.accum("<![CDATA[");
+ this.accum(ch, start, length);
+ // this.accum("]]>");
}
catch(IOException ioe)
{
@@ -912,29 +1020,22 @@
public void processingInstruction (String target, String data)
throws SAXException
{
- try
+ // Use a fairly nasty hack to tell if the next node is supposed to be
+ // unescaped text.
+ if(target.equals("xslt-next-is-raw") && data.equals("formatter-to-dom"))
{
- // Use a fairly nasty hack to tell if the next node is supposed to be
- // unescaped text.
- if(target.equals("xslt-next-is-raw") &&
data.equals("formatter-to-dom"))
- {
- m_nextIsRaw = true;
- }
- else
- {
- writeParentTagEnd();
- if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
- this.m_writer.write("<?" + target);
- if (data.length() > 0 && !Character.isSpaceChar(data.charAt(0)))
- this.m_writer.write(" ");
- this.m_writer.write(data + ">"); // different from XML
- m_startNewLine = true;
- }
+ m_nextIsRaw = true;
}
- catch(IOException ioe)
+ else
{
- throw new SAXException("IO error", ioe);
+ writeParentTagEnd();
+ if (shouldIndent())
+ indent(m_currentIndent);
+ this.accum("<?" + target);
+ if (data.length() > 0 && !Character.isSpaceChar(data.charAt(0)))
+ this.accum(" ");
+ this.accum(data + ">"); // different from XML
+ m_startNewLine = true;
}
}
@@ -944,16 +1045,10 @@
public void entityReference(String name)
throws SAXException
{
- try
- {
- this.m_writer.write("&");
- this.m_writer.write(name);
- this.m_writer.write(";");
- }
- catch(IOException ioe)
- {
- throw new SAXException("IO error", ioe);
- }
+ this.accum("&");
+ this.accum(name);
+ this.accum(";");
}
+
}
1.10 +496 -338
xml-xalan/src/org/apache/xalan/xpath/xml/FormatterToXML.java
Index: FormatterToXML.java
===================================================================
RCS file:
/home/cvs/xml-xalan/src/org/apache/xalan/xpath/xml/FormatterToXML.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- FormatterToXML.java 1999/12/03 08:43:13 1.9
+++ FormatterToXML.java 1999/12/13 07:35:49 1.10
@@ -79,6 +79,10 @@
* The writer where the XML will be written.
*/
protected Writer m_writer = null;
+
+ protected OutputStream m_outputStream = null;
+
+ private boolean m_bytesEqualChars = false;
/**
* Return the Writer.
@@ -125,7 +129,7 @@
* A stack of Boolean objects that tell if the given element
* has children.
*/
- protected Stack m_elemStack = new Stack();
+ protected BoolStack m_elemStack = new BoolStack();
/**
* Use the system line seperator to write line breaks.
@@ -139,6 +143,18 @@
protected final int m_lineSepLen = m_lineSep.length();
/**
+ * Output a system-dependent line break.
+ */
+ protected final void outputLineSep()
+ throws SAXException
+ {
+ for(int z = 0; z < m_lineSepLen; z++)
+ {
+ accum(m_lineSep.charAt(z));
+ }
+ }
+
+ /**
* State flag to tell if preservation of whitespace
* is important.
*/
@@ -148,7 +164,7 @@
* Stack to keep track of whether or not we need to
* preserve whitespace.
*/
- protected Stack m_preserves = new Stack();
+ protected BoolStack m_preserves = new BoolStack();
/**
* State flag that tells if the previous node processed
@@ -215,8 +231,60 @@
/**
* These are characters that will be escaped in the output.
+ */
+ // public char[] m_attrSpecialChars = {'<', '>', '&', '\"', '\r', '\n'};
+ public char[] m_attrSpecialChars = {'<', '>', '&', '\"'};
+
+ static final int SPECIALSSIZE = 256;
+
+ public char[] m_attrCharsMap = new char[SPECIALSSIZE];
+
+ public char[] m_charsMap = new char[SPECIALSSIZE];
+
+ /**
+ * Set the attribute characters what will require special mapping.
+ */
+ protected void initAttrCharsMap()
+ {
+ int n = (m_maxCharacter > SPECIALSSIZE) ? SPECIALSSIZE : m_maxCharacter;
+ for(int i = 0; i < n; i++)
+ {
+ m_attrCharsMap[i] = '\0';
+ }
+ int nSpecials = m_attrSpecialChars.length;
+ for(int i = 0; i < nSpecials; i++)
+ {
+ m_attrCharsMap[(int)i] = 'S';
+ }
+ }
+
+ /**
+ * Set the characters what will require special mapping.
*/
- public String m_attrSpecialChars = "<>&\"\r\n";
+ protected void initCharsMap()
+ {
+ initAttrCharsMap();
+ int n = (m_maxCharacter > SPECIALSSIZE) ? SPECIALSSIZE : m_maxCharacter;
+ for(int i = 0; i < n; i++)
+ {
+ m_charsMap[i] = '\0';
+ }
+ m_charsMap[(int)'\n'] = 'S';
+ m_charsMap[(int)'<'] = 'S';
+ m_charsMap[(int)'>'] = 'S';
+ m_charsMap[(int)'&'] = 'S';
+ for(int i = 0; i < 20; i++)
+ {
+ m_charsMap[i] = 'S';
+ }
+ m_charsMap[10] = '\0';
+ m_charsMap[13] = '\0';
+ m_charsMap[9] = '\0';
+ for(int i = m_maxCharacter; i < SPECIALSSIZE; i++)
+ {
+ m_charsMap[i] = 'S';
+ }
+ }
/**
* Flag to quickly tell if the encoding is UTF8.
@@ -252,7 +320,54 @@
{
m_writer = writer;
initEncodings();
+ throw new RuntimeException("Constructor not implemented!");
+ }
+
+ /**
+ * Constructor using a writer.
+ * @param writer The character output stream to use.
+ */
+ public FormatterToXML(FormatterToXML xmlListener)
+ {
+ m_writer = xmlListener.m_writer;
+ m_outputStream = xmlListener.m_outputStream;
+ m_bytesEqualChars = xmlListener.m_bytesEqualChars;
+ m_stripCData = xmlListener.m_stripCData;
+ m_escapeCData = xmlListener.m_escapeCData;
+ m_encoding = xmlListener.m_encoding;
+ javaEncodingIsISO = xmlListener.javaEncodingIsISO;
+ m_shouldNotWriteXMLHeader = xmlListener.m_shouldNotWriteXMLHeader;
+ m_shouldNotWriteXMLHeader = xmlListener.m_shouldNotWriteXMLHeader;
+ m_elemStack = xmlListener.m_elemStack;
+ // m_lineSep = xmlListener.m_lineSep;
+ // m_lineSepLen = xmlListener.m_lineSepLen;
+ m_ispreserve = xmlListener.m_ispreserve;
+ m_preserves = xmlListener.m_preserves;
+ m_isprevtext = xmlListener.m_isprevtext;
+ m_doIndent = xmlListener.m_doIndent;
+ m_currentIndent = xmlListener.m_currentIndent;
+ indent = xmlListener.indent;
+ level = xmlListener.level;
+ m_startNewLine = xmlListener.m_startNewLine;
+ m_needToOutputDocTypeDecl = xmlListener.m_needToOutputDocTypeDecl;
+ m_nextIsRaw = xmlListener.m_nextIsRaw;
+ m_doctypeSystem = xmlListener.m_doctypeSystem;
+ m_doctypePublic = xmlListener.m_doctypePublic;
+ m_standalone = xmlListener.m_standalone;
+ m_mediatype = xmlListener.m_mediatype;
+ m_attrSpecialChars = xmlListener.m_attrSpecialChars;
+ m_attrCharsMap = xmlListener.m_attrCharsMap;
+ m_charsMap = xmlListener.m_charsMap;
+ m_maxCharacter = xmlListener.m_maxCharacter;
+ m_spaceBeforeClose = xmlListener.m_spaceBeforeClose;
+ m_inCData = xmlListener.m_inCData;
+ m_charBuf = xmlListener.m_charBuf;
+ m_byteBuf = xmlListener.m_byteBuf;
+ // m_pos = xmlListener.m_pos;
+ m_pos = 0;
+ initCharsMap();
}
+
/**
* Initialize the serializer with the specified writer and output format.
@@ -279,6 +394,7 @@
}
// Determine the last printable character based on the output format
m_maxCharacter = format.getLastPrintable();
+ initCharsMap();
if(null == this.m_encoding)
this.m_encoding = getMimeEncoding(format.getEncoding());
@@ -290,6 +406,7 @@
{
Character maxChar = (Character)maxCharObj;
m_maxCharacter = maxChar.charValue();
+ initCharsMap();
}
}
@@ -309,9 +426,21 @@
{
this.m_encoding = getMimeEncoding(format.getEncoding());
- String javaEncoding = this.convertMime2JavaEncoding(this.m_encoding);
-
- init( new OutputStreamWriter( output, javaEncoding ), format );
+ if(this.m_encoding.equals(DEFAULT_MIME_ENCODING) ||
+ this.m_encoding.equals("WINDOWS-1250") ||
+ this.m_encoding.equals("US-ASCII") ||
+ this.m_encoding.equals("US-ASCII"))
+ {
+ m_bytesEqualChars = true;
+ m_outputStream = output;
+ init( (Writer)null, format );
+ }
+ else
+ {
+ String javaEncoding = this.convertMime2JavaEncoding(this.m_encoding);
+
+ init( new OutputStreamWriter( output, javaEncoding ), format );
+ }
}
/**
@@ -335,50 +464,36 @@
public void startDocument ()
throws SAXException
{
- try
+ m_needToOutputDocTypeDecl = true;
+ m_startNewLine = false;
+
+ if(m_shouldNotWriteXMLHeader == false)
{
- m_needToOutputDocTypeDecl = true;
- m_startNewLine = false;
+ String encoding = getMimeEncoding(this.m_encoding);
- if(m_shouldNotWriteXMLHeader == false)
- {
- String encoding = getMimeEncoding(this.m_encoding);
-
- String version = (null == m_version) ? "1.0" : m_version;
-
- m_writer.write("<?xml version=\""+version+"\" encoding=\""+
- encoding + "\"?>");
- m_writer.write(m_lineSep);
- }
- }
- catch(IOException ioe)
- {
- throw new SAXException("IO error", ioe);
- }
+ String version = (null == m_version) ? "1.0" : m_version;
+
+ accum("<?xml version=\""+version+"\" encoding=\""+
+ encoding + "\"?>");
+ outputLineSep();
+ }
if((true == m_needToOutputDocTypeDecl) && (null != m_doctypeSystem))
{
- try
- {
- m_writer.write("<!DOCTYPE ");
-
- if(null != m_doctypePublic)
- {
- m_writer.write(" PUBLIC \"");
- m_writer.write(m_doctypePublic);
- m_writer.write("\"");
- }
- if(null == m_doctypePublic)
- m_writer.write(" SYSTEM \"");
- else
- m_writer.write(" \"");
- m_writer.write(m_doctypeSystem);
- m_writer.write("\">");
- m_writer.write(m_lineSep);
- }
- catch(IOException ioe)
+ accum("<!DOCTYPE ");
+
+ if(null != m_doctypePublic)
{
- throw new SAXException("IO error", ioe);
+ accum(" PUBLIC \"");
+ accum(m_doctypePublic);
+ accum("\"");
}
+ if(null == m_doctypePublic)
+ accum(" SYSTEM \"");
+ else
+ accum(" \"");
+ accum(m_doctypeSystem);
+ accum("\">");
+ outputLineSep();
}
m_needToOutputDocTypeDecl = false;
}
@@ -392,18 +507,11 @@
public void endDocument ()
throws SAXException
{
- try
+ if(m_doIndent && !m_isprevtext)
{
- if(m_doIndent && !m_isprevtext)
- {
- this.m_writer.write(m_lineSep);
- }
- this.m_writer.flush();
+ outputLineSep();
}
- catch(IOException ioe)
- {
- throw new SAXException("IO error", ioe);
- }
+ flush();
}
/**
@@ -454,36 +562,29 @@
public void startElement (String name, AttributeList atts)
throws SAXException
{
- try
- {
- writeParentTagEnd();
- m_ispreserve = false;
- // System.out.println(name+": m_doIndent = "+m_doIndent+",
m_ispreserve = "+m_ispreserve+", m_isprevtext = "+m_isprevtext);
- if (shouldIndent() && !m_elemStack.isEmpty())
- {
- m_startNewLine = true;
- indent(this.m_writer, m_currentIndent);
- }
-
- this.m_writer.write('<');
- this.m_writer.write(name);
-
- int nAttrs = atts.getLength();
- for (int i = 0; i < nAttrs ; i++)
- {
- processAttribute(atts.getName(i), atts.getValue(i));
- }
- // Flag the current element as not yet having any children.
- openElementForChildren();
-
- m_currentIndent += this.indent;
-
- m_isprevtext = false;
+ writeParentTagEnd();
+ m_ispreserve = false;
+ // System.out.println(name+": m_doIndent = "+m_doIndent+", m_ispreserve
= "+m_ispreserve+", m_isprevtext = "+m_isprevtext);
+ if (shouldIndent() && !m_elemStack.isEmpty())
+ {
+ m_startNewLine = true;
+ indent(m_currentIndent);
}
- catch(IOException ioe)
+
+ accum('<');
+ accum(name);
+
+ int nAttrs = atts.getLength();
+ for (int i = 0; i < nAttrs ; i++)
{
- throw new SAXException("IO error", ioe);
+ processAttribute(atts.getName(i), atts.getValue(i));
}
+ // Flag the current element as not yet having any children.
+ openElementForChildren();
+
+ m_currentIndent += this.indent;
+
+ m_isprevtext = false;
}
/**
@@ -493,25 +594,18 @@
protected void writeParentTagEnd()
throws SAXException
{
- try
+ if(!m_elemStack.isEmpty())
{
- if(!m_elemStack.empty())
+ // See if the parent element has already been flagged as having
children.
+ if((false == m_elemStack.peek()))
{
- // See if the parent element has already been flagged as having
children.
- if(false == ((Boolean)m_elemStack.peek()).booleanValue())
- {
- this.m_writer.write('>');
- m_isprevtext = false;
- m_elemStack.pop();
- m_elemStack.push(new Boolean(true));
- m_preserves.push(new Boolean(m_ispreserve));
- }
+ accum('>');
+ m_isprevtext = false;
+ m_elemStack.pop();
+ m_elemStack.push(true);
+ m_preserves.push(m_ispreserve);
}
}
- catch(IOException ioe)
- {
- throw new SAXException("IO error", ioe);
- }
}
/**
@@ -521,7 +615,7 @@
protected void openElementForChildren()
{
// Flag the current element as not yet having any children.
- m_elemStack.push(new Boolean(false));
+ m_elemStack.push(false);
}
/**
@@ -531,7 +625,7 @@
protected boolean childNodesWereAdded()
{
return m_elemStack.isEmpty() ?
- false : ((Boolean)m_elemStack.pop()).booleanValue();
+ false : m_elemStack.pop();
}
/**
@@ -544,36 +638,30 @@
public void endElement (String name)
throws SAXException
{
- try
+ m_currentIndent -= this.indent;
+ boolean hasChildNodes = childNodesWereAdded();
+ if (hasChildNodes)
+ {
+ if (shouldIndent())
+ indent(m_currentIndent);
+ accum('<');
+ accum('/');
+ accum(name);
+ accum('>');
+ }
+ else
{
- m_currentIndent -= this.indent;
- boolean hasChildNodes = childNodesWereAdded();
- if (hasChildNodes)
- {
- if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
- this.m_writer.write("</");
- this.m_writer.write(name);
- this.m_writer.write('>');
- }
+ if(m_spaceBeforeClose)
+ accum(" />");
else
- {
- if(m_spaceBeforeClose)
- this.m_writer.write(" />");
- else
- this.m_writer.write("/>");
- }
- if (hasChildNodes)
- {
- m_ispreserve = m_preserves.isEmpty()
- ? false : ((Boolean)m_preserves.pop()).booleanValue();
- }
- m_isprevtext = false;
+ accum("/>");
}
- catch(IOException ioe)
+ if (hasChildNodes)
{
- throw new SAXException("IO error", ioe);
+ m_ispreserve = m_preserves.isEmpty()
+ ? false : m_preserves.pop();
}
+ m_isprevtext = false;
}
/**
@@ -584,18 +672,11 @@
protected void processAttribute(String name, String value)
throws SAXException
{
- try
- {
- this.m_writer.write(' ');
- this.m_writer.write(name);
- this.m_writer.write("=\"");
- this.m_writer.write(prepAttrString(value, m_attrSpecialChars,
this.m_encoding));
- this.m_writer.write('\"');
- }
- catch(IOException ioe)
- {
- throw new SAXException("IO error", ioe);
- }
+ accum(' ');
+ accum(name);
+ accum("=\"");
+ writeAttrString(value, this.m_encoding);
+ accum('\"');
}
/**
@@ -610,29 +691,25 @@
public void processingInstruction (String target, String data)
throws SAXException
{
- try
+ // Use a fairly nasty hack to tell if the next node is supposed to be
+ // unescaped text.
+ if(target.equals("xslt-next-is-raw") && data.equals("formatter-to-dom"))
{
- // Use a fairly nasty hack to tell if the next node is supposed to be
- // unescaped text.
- if(target.equals("xslt-next-is-raw") &&
data.equals("formatter-to-dom"))
- {
- m_nextIsRaw = true;
- }
- else
- {
- writeParentTagEnd();
- if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
- this.m_writer.write("<?" + target);
- if (data.length() > 0 && !Character.isSpaceChar(data.charAt(0)))
- this.m_writer.write(" ");
- this.m_writer.write(data + "?>");
- m_startNewLine = true;
- }
+ m_nextIsRaw = true;
}
- catch(IOException ioe)
+ else
{
- throw new SAXException("IO error", ioe);
+ writeParentTagEnd();
+ if (shouldIndent())
+ indent(m_currentIndent);
+ accum('<');
+ accum('?');
+ accum(target);
+ if (data.length() > 0 && !Character.isSpaceChar(data.charAt(0)))
+ accum(' ');
+ accum('?');
+ accum('>');
+ m_startNewLine = true;
}
}
@@ -651,20 +728,13 @@
public void comment (char ch[], int start, int length)
throws SAXException
{
- try
- {
- writeParentTagEnd();
- if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
- this.m_writer.write("<!--");
- this.m_writer.write(ch, start, length);
- this.m_writer.write("-->");
- m_startNewLine = true;
- }
- catch(IOException ioe)
- {
- throw new SAXException(ioe);
- }
+ writeParentTagEnd();
+ if (shouldIndent())
+ indent(m_currentIndent);
+ accum("<!--");
+ accum(ch, start, length);
+ accum("-->");
+ m_startNewLine = true;
}
protected boolean m_inCData = false;
@@ -738,21 +808,21 @@
writeParentTagEnd();
m_ispreserve = true;
if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
+ indent(m_currentIndent);
if(!m_stripCData)
{
if(((length >= 1) && (ch[start] <= m_maxCharacter)))
{
- this.m_writer.write("<![CDATA[");
+ accum("<![CDATA[");
}
}
- // this.m_writer.write(ch, start, length);
+ // accum(ch, start, length);
writeNormalizedChars(ch, start, length, !m_stripCData);
if(!m_stripCData)
{
if(((length >= 1) && (ch[(start+length)-1] <= m_maxCharacter)))
{
- this.m_writer.write("]]>");
+ accum("]]>");
}
}
}
@@ -763,11 +833,151 @@
}
}
- static final int MAXCHARBUF = 4096;
- static final int MAXSAFECHARBUF = MAXCHARBUF-256;
- char[] m_charBuf = new char[MAXCHARBUF];
+ static final int MAXCHARBUF = (8*1024);
+ protected char[] m_charBuf = new char[MAXCHARBUF];
+ protected byte[] m_byteBuf = new byte[MAXCHARBUF];
+ protected int m_pos = 0;
/**
+ * Append a byte to the buffer.
+ */
+ protected final void accum(byte b)
+ throws SAXException
+ {
+ if(m_bytesEqualChars)
+ {
+ m_byteBuf[m_pos++] = b;
+ if(m_pos >= MAXCHARBUF)
+ flushBytes();
+ }
+ else
+ {
+ m_charBuf[m_pos++] = (char)b;
+ if(m_pos >= MAXCHARBUF)
+ flushChars();
+ }
+ }
+
+ /**
+ * Append a character to the buffer.
+ */
+ protected final void accum(char b)
+ throws SAXException
+ {
+ if(m_bytesEqualChars)
+ {
+ m_byteBuf[m_pos++] = (byte)b;
+ if(m_pos >= MAXCHARBUF)
+ flushBytes();
+ }
+ else
+ {
+ m_charBuf[m_pos++] = b;
+ if(m_pos >= MAXCHARBUF)
+ flushChars();
+ }
+ }
+
+ /**
+ * Append a character to the buffer.
+ */
+ protected final void accum(char chars[], int start, int length)
+ throws SAXException
+ {
+ int n = start+length;
+ if(m_bytesEqualChars)
+ {
+ for(int i = start; i < n; i++)
+ {
+ m_byteBuf[m_pos++] = (byte)chars[i];
+ if(m_pos >= MAXCHARBUF)
+ flushBytes();
+ }
+ }
+ else
+ {
+ for(int i = start; i < n; i++)
+ {
+ m_charBuf[m_pos++] = chars[i];
+ if(m_pos >= MAXCHARBUF)
+ flushChars();
+ }
+ }
+ }
+
+ /**
+ * Append a character to the buffer.
+ */
+ protected final void accum(String s)
+ throws SAXException
+ {
+ int n = s.length();
+
+ if(m_bytesEqualChars)
+ {
+ char[] chars = s.toCharArray();
+ for(int i = 0; i < n; i++)
+ {
+ m_byteBuf[m_pos++] = (byte)chars[i];;
+ if(m_pos >= MAXCHARBUF)
+ flushBytes();
+ }
+ }
+ else
+ {
+ for(int i = 0; i < n; i++)
+ {
+ m_charBuf[m_pos++] = s.charAt(i);;
+ if(m_pos >= MAXCHARBUF)
+ flushChars();
+ }
+ }
+ }
+
+ private final void flushBytes()
+ throws SAXException
+ {
+ try
+ {
+ // System.out.println("Flushing bytes...");
+ this.m_outputStream.write(m_byteBuf, 0, m_pos);
+ m_pos = 0;
+ }
+ catch(IOException ioe)
+ {
+ throw new SAXException(ioe);
+ }
+ }
+
+ private final void flushChars()
+ throws SAXException
+ {
+ try
+ {
+ // System.out.println("Flushing chars...");
+ this.m_writer.write(m_charBuf, 0, m_pos);
+ m_pos = 0;
+ }
+ catch(IOException ioe)
+ {
+ throw new SAXException(ioe);
+ }
+ }
+
+ protected final void flush()
+ throws SAXException
+ {
+ if(m_bytesEqualChars)
+ {
+ flushBytes();
+ }
+ else
+ {
+ flushChars();
+ }
+ }
+
+ /**
* Receive notification of character data.
*
* <p>The Parser will call this method to report each chunk of
@@ -811,44 +1021,45 @@
return;
}
- try
+ writeParentTagEnd();
+ m_ispreserve = true;
+
+ int pos = 0;
+ int end = start+length;
+ for (int i = start; i < end; i ++)
{
- writeParentTagEnd();
- m_ispreserve = true;
- int pos = 0;
- int end = start+length;
- for (int i = start; i < end; i ++)
+ char ch = chars[i];
+ if((ch < SPECIALSSIZE) && (m_charsMap[ch] != 'S'))
{
- char ch = chars[i];
- int chNum = (int)ch;
+ accum(ch);
+ }
+ else
+ {
if ('\n' == ch)
{
- for(int k = 0; k < m_lineSepLen; k++)
- {
- m_charBuf[pos++] = m_lineSep.charAt(k);
- }
+ outputLineSep();
}
else if ('<' == ch)
{
- m_charBuf[pos++] = '&';
- m_charBuf[pos++] = 'l';
- m_charBuf[pos++] = 't';
- m_charBuf[pos++] = ';';
+ accum('&');
+ accum('l');
+ accum('t');
+ accum(';');
}
else if ('>' == ch)
{
- m_charBuf[pos++] = '&';
- m_charBuf[pos++] = 'g';
- m_charBuf[pos++] = 't';
- m_charBuf[pos++] = ';';
+ accum('&');
+ accum('g');
+ accum('t');
+ accum(';');
}
else if ('&' == ch)
{
- m_charBuf[pos++] = '&';
- m_charBuf[pos++] = 'a';
- m_charBuf[pos++] = 'm';
- m_charBuf[pos++] = 'p';
- m_charBuf[pos++] = ';';
+ accum('&');
+ accum('a');
+ accum('m');
+ accum('p');
+ accum(';');
/**
} else if ('"' == ch) {
sb.append(""");
@@ -856,7 +1067,7 @@
sb.append("'");
*/
}
- else if (m_isUTF8 && (0xd800 <= chNum && chNum < 0xdc00))
+ else if (m_isUTF8 && (0xd800 <= ch && ch < 0xdc00))
{
// UTF-16 surrogate
int next;
@@ -873,63 +1084,37 @@
+Integer.toHexString(ch)+" "+Integer.toHexString(next));
next = ((ch-0xd800)<<10)+next-0xdc00+0x00010000;
}
- m_charBuf[pos++] = '&';
- m_charBuf[pos++] = '#';
- m_charBuf[pos++] = 'x';
+ accum('&');
+ accum('#');
+ accum('x');
String intStr = Integer.toHexString(next);
int nIntStr = intStr.length();
for(int k = 0; k < nIntStr; k++)
{
- m_charBuf[pos++] = intStr.charAt(k);
+ accum(intStr.charAt(k));
}
- m_charBuf[pos++] = ';';
+ accum(';');
/*} else if (null != ctbc && !ctbc.canConvert(ch)) {
sb.append("&#x");
sb.append(Integer.toString((int)ch, 16));
sb.append(";");*/
}
- else if((((chNum >= 20) && (chNum <= 126))
- || (chNum == 10)
- || (chNum == 13)
- || (chNum == 9)))
- {
- // System.out.println("ch: "+ch);
- m_charBuf[pos++] = ch;
- }
- else if((chNum >= 20) && (ch <= m_maxCharacter))
- {
- // System.out.println("ch(2): "+ch);
- // Hope this is right...
- m_charBuf[pos++] = ch;
- }
else
{
- m_charBuf[pos++] = '&';
- m_charBuf[pos++] = '#';
- String intStr = Integer.toString(chNum);
+ accum('&');
+ accum('#');
+ String intStr = Integer.toString(ch);
int nIntStr = intStr.length();
for(int k = 0; k < nIntStr; k++)
{
- m_charBuf[pos++] = intStr.charAt(k);
+ accum(intStr.charAt(k));
}
- m_charBuf[pos++] = ';';
+ accum(';');
}
- // Use 80 as a best guess safe buffer
- if(pos > MAXSAFECHARBUF)
- {
- this.m_writer.write(m_charBuf, 0, pos);
- pos = 0;
- }
}
-
- // System.out.println(new String(m_charBuf, 0, pos));
- this.m_writer.write(m_charBuf, 0, pos);
- m_isprevtext = true;
- }
- catch(IOException ioe)
- {
- throw new SAXException("FormatterToXML.characters io error", ioe);
}
+
+ m_isprevtext = true;
}
/**
@@ -939,17 +1124,9 @@
public void charactersRaw (char ch[], int start, int length)
throws SAXException
{
- try
- {
- writeParentTagEnd();
- m_ispreserve = true;
- m_writer.write(ch, start, length);
- m_writer.flush();
- }
- catch(IOException ioe)
- {
- throw new SAXException("FormatterToXML.charactersRaw io error", ioe);
- }
+ writeParentTagEnd();
+ m_ispreserve = true;
+ accum(ch, start, length);
}
/**
@@ -964,12 +1141,12 @@
char c = ch[i];
if('\n' == c)
{
- this.m_writer.write(m_lineSep);
+ outputLineSep();
}
else if(isCData && (c > m_maxCharacter))
{
if(i != 0)
- this.m_writer.write("]]>");
+ accum("]]>");
// This needs to go into a function...
if (0xd800 <= ((int)c) && ((int)c) < 0xdc00)
{
@@ -988,31 +1165,33 @@
+Integer.toHexString((int)c)+" "+Integer.toHexString(next));
next = ((c-0xd800)<<10)+next-0xdc00+0x00010000;
}
- this.m_writer.write("&#x");
- this.m_writer.write(Integer.toHexString(next));
- this.m_writer.write(";");
+ accum('&');
+ accum('#');
+ accum('x');
+ accum(Integer.toHexString(next));
+ accum(';');
}
else
{
- this.m_writer.write("&#");
+ accum("&#");
String intStr = Integer.toString((int)c);
- this.m_writer.write(intStr);
- this.m_writer.write(';');
+ accum(intStr);
+ accum(';');
}
if((i != 0) && (i < (end-1)))
- this.m_writer.write("<![CDATA[");
+ accum("<![CDATA[");
}
else if(isCData && ((i < (end-2)) && (']' == c) &&
(']' == ch[i+1]) && ('>' == ch[i+2])))
{
- this.m_writer.write("]]]]><![CDATA[>");
+ accum("]]]]><![CDATA[>");
i+=2;
}
else
{
if(c <= m_maxCharacter)
{
- this.m_writer.write(c);
+ accum(c);
}
// This needs to go into a function...
else if (0xd800 <= ((int)c) && ((int)c) < 0xdc00)
@@ -1032,16 +1211,16 @@
+Integer.toHexString((int)c)+" "+Integer.toHexString(next));
next = ((c-0xd800)<<10)+next-0xdc00+0x00010000;
}
- this.m_writer.write("&#x");
- this.m_writer.write(Integer.toHexString(next));
- this.m_writer.write(";");
+ accum("&#x");
+ accum(Integer.toHexString(next));
+ accum(";");
}
else
{
- this.m_writer.write("&#");
+ accum("&#");
String intStr = Integer.toString((int)c);
- this.m_writer.write(intStr);
- this.m_writer.write(';');
+ accum(intStr);
+ accum(';');
}
}
}
@@ -1108,19 +1287,12 @@
public void entityReference(String name)
throws SAXException
{
- try
- {
- writeParentTagEnd();
- if (shouldIndent())
- indent(this.m_writer, m_currentIndent);
- this.m_writer.write("&");
- this.m_writer.write(name);
- this.m_writer.write(";");
- }
- catch(IOException ioe)
- {
- throw new SAXException("FormatterToXML.entityReference io error", ioe);
- }
+ writeParentTagEnd();
+ if (shouldIndent())
+ indent(m_currentIndent);
+ accum("&");
+ accum(name);
+ accum(";");
}
/**
@@ -1133,53 +1305,53 @@
* @return XML-formatted string.
* @see #backReference
*/
- public String prepAttrString(String string, String specials, String
encoding)
+ public void writeAttrString(String string, String encoding)
throws SAXException
{
- StringBuffer sb = new StringBuffer(string.length()*12/10);
-
- for (int i = 0; i < string.length(); i ++)
+ char[] stringChars = string.toCharArray();
+ int len = stringChars.length;
+ for (int i = 0; i < len; i ++)
{
- char ch = string.charAt(i);
- int chNum = (int)ch;
- int index = specials.indexOf(chNum);
- if (index >= 0)
+ char ch = stringChars[i];
+ if((ch < SPECIALSSIZE) && (m_attrCharsMap[ch] != 'S'))
{
- sb.append("&#");
- sb.append(Integer.toString(ch));
- sb.append(";");
+ accum(ch);
}
- else if (0xd800 <= chNum && chNum < 0xdc00)
+ else
{
- // UTF-16 surrogate
- int next;
- if (i+1 >= string.length())
+ if (0xd800 <= ch && ch < 0xdc00)
{
- throw new SAXException("Invalid UTF-16 surrogate detected: "
- +Integer.toHexString(ch)+ " ?");
+ // UTF-16 surrogate
+ int next;
+ if (i+1 >= string.length())
+ {
+ throw new SAXException("Invalid UTF-16 surrogate detected: "
+ +Integer.toHexString(ch)+ " ?");
+ }
+ else
+ {
+ next = string.charAt(++i);
+ if (!(0xdc00 <= next && next < 0xe000))
+ throw new SAXException("Invalid UTF-16 surrogate detected: "
+ +Integer.toHexString(ch)+" "+Integer.toHexString(next));
+ next = ((ch-0xd800)<<10)+next-0xdc00+0x00010000;
+ }
+ accum("&#x");
+ accum(Integer.toHexString(next));
+ accum(";");
+ /*} else if (null != ctbc && !ctbc.canConvert(ch)) {
+ sb.append("&#x");
+ sb.append(Integer.toString((int)ch, 16));
+ sb.append(";");*/
}
else
{
- next = string.charAt(++i);
- if (!(0xdc00 <= next && next < 0xe000))
- throw new SAXException("Invalid UTF-16 surrogate detected: "
- +Integer.toHexString(ch)+" "+Integer.toHexString(next));
- next = ((ch-0xd800)<<10)+next-0xdc00+0x00010000;
+ accum("&#");
+ accum(Integer.toString(ch));
+ accum(";");
}
- sb.append("&#x");
- sb.append(Integer.toHexString(next));
- sb.append(";");
- /*} else if (null != ctbc && !ctbc.canConvert(ch)) {
- sb.append("&#x");
- sb.append(Integer.toString((int)ch, 16));
- sb.append(";");*/
- }
- else
- {
- sb.append(ch);
}
}
- return sb.toString();
}
protected boolean shouldIndent()
@@ -1193,17 +1365,10 @@
* @param n Number of spaces to print.
* @exception IOException Thrown if <var>pw</var> is invalid.
*/
- public static void printSpace(java.io.Writer pw, int n) throws
SAXException
+ public void printSpace(int n) throws SAXException
{
- try
- {
- for (int i = 0; i < n; i ++)
- pw.write(" ");
- }
- catch(IOException ioe)
- {
- throw new SAXException("FormatterToXML.printSpace error", ioe);
- }
+ for (int i = 0; i < n; i ++)
+ accum(' ');
}
/**
@@ -1212,21 +1377,14 @@
* @param n Number of spaces to print.
* @exception IOException Thrown if <var>pw</var> is invalid.
*/
- public void indent(java.io.Writer pw, int n) throws SAXException
+ public void indent(int n) throws SAXException
{
- try
- {
- if(m_startNewLine)
- pw.write(m_lineSep);
-
- if(m_doIndent)
- {
- printSpace(pw, n);
- }
- }
- catch(IOException ioe)
+ if(m_startNewLine)
+ outputLineSep();
+
+ if(m_doIndent)
{
- throw new SAXException("FormatterToXML.indent error", ioe);
+ printSpace(n);
}
}