| Method from com.sun.org.apache.xml.internal.serializer.ToStream Detail: |
protected int accumDefaultEntity(Writer writer,
char ch,
int i,
char[] chars,
int len,
boolean fromTextNode,
boolean escLF) throws IOException {
if (!escLF && CharInfo.S_LINEFEED == ch)
{
writer.write(m_lineSep, 0, m_lineSepLen);
}
else
{
// if this is text node character and a special one of those,
// or if this is a character from attribute value and a special one of those
if ((fromTextNode && m_charInfo.isSpecialTextChar(ch)) || (!fromTextNode && m_charInfo.isSpecialAttrChar(ch)))
{
String outputStringForChar = m_charInfo.getOutputStringForChar(ch);
if (null != outputStringForChar)
{
writer.write(outputStringForChar);
}
else
return i;
}
else
return i;
}
return i + 1;
}
Handle one of the default entities, return false if it
is not a default entity. |
protected int accumDefaultEscape(Writer writer,
char ch,
int i,
char[] chars,
int len,
boolean fromTextNode,
boolean escLF) throws IOException {
int pos = accumDefaultEntity(writer, ch, i, chars, len, fromTextNode, escLF);
if (i == pos)
{
if (Encodings.isHighUTF16Surrogate(ch))
{
// Should be the UTF-16 low surrogate of the hig/low pair.
char next;
// Unicode code point formed from the high/low pair.
int codePoint = 0;
if (i + 1 >= len)
{
throw new IOException(
Utils.messages.createMessage(
MsgKey.ER_INVALID_UTF16_SURROGATE,
new Object[] { Integer.toHexString(ch)}));
//"Invalid UTF-16 surrogate detected: "
//+Integer.toHexString(ch)+ " ?");
}
else
{
next = chars[++i];
if (!(Encodings.isLowUTF16Surrogate(next)))
throw new IOException(
Utils.messages.createMessage(
MsgKey
.ER_INVALID_UTF16_SURROGATE,
new Object[] {
Integer.toHexString(ch)
+ " "
+ Integer.toHexString(next)}));
//"Invalid UTF-16 surrogate detected: "
//+Integer.toHexString(ch)+" "+Integer.toHexString(next));
codePoint = Encodings.toCodePoint(ch,next);
}
writer.write("");
writer.write(Integer.toString(codePoint));
writer.write(';");
pos += 2; // count the two characters that went into writing out this entity
}
else
{
/* This if check is added to support control characters in XML 1.1.
* If a character is a Control Character within C0 and C1 range, it is desirable
* to write it out as Numeric Character Reference(NCR) regardless of XML Version
* being used for output document.
*/
if (isCharacterInC0orC1Range(ch) ||
(XMLVERSION11.equals(getVersion()) && isNELorLSEPCharacter(ch)))
{
writer.write("");
writer.write(Integer.toString(ch));
writer.write(';");
}
else if ((!escapingNotNeeded(ch) ||
( (fromTextNode && m_charInfo.isSpecialTextChar(ch))
|| (!fromTextNode && m_charInfo.isSpecialAttrChar(ch))))
&& m_elemContext.m_currentElemDepth > 0)
{
writer.write("");
writer.write(Integer.toString(ch));
writer.write(';");
}
else
{
writer.write(ch);
}
pos++; // count the single character that was processed
}
}
return pos;
}
Escape and writer.write a character. |
public boolean addAttributeAlways(String uri,
String localName,
String rawName,
String type,
String value,
boolean xslAttribute) {
boolean was_added;
int index;
//if (uri == null || localName == null || uri.length() == 0)
index = m_attributes.getIndex(rawName);
// Don't use 'localName' as it gives incorrect value, rely only on 'rawName'
/*else {
index = m_attributes.getIndex(uri, localName);
}*/
if (index >= 0)
{
String old_value = null;
if (m_tracer != null)
{
old_value = m_attributes.getValue(index);
if (value.equals(old_value))
old_value = null;
}
/* We've seen the attribute before.
* We may have a null uri or localName, but all we really
* want to re-set is the value anyway.
*/
m_attributes.setValue(index, value);
was_added = false;
if (old_value != null){
firePseudoAttributes();
}
}
else
{
// the attribute doesn't exist yet, create it
if (xslAttribute)
{
/*
* This attribute is from an xsl:attribute element so we take some care in
* adding it, e.g.
* < elem1 foo:attr1="1" xmlns:foo="uri1" >
* < xsl:attribute name="foo:attr2" >2< /xsl:attribute >
* < /elem1 >
*
* We are adding attr1 and attr2 both as attributes of elem1,
* and this code is adding attr2 (the xsl:attribute ).
* We could have a collision with the prefix like in the example above.
*/
// In the example above, is there a prefix like foo ?
final int colonIndex = rawName.indexOf(':");
if (colonIndex > 0)
{
String prefix = rawName.substring(0,colonIndex);
NamespaceMappings.MappingRecord existing_mapping = m_prefixMap.getMappingFromPrefix(prefix);
/* Before adding this attribute (foo:attr2),
* is the prefix for it (foo) already mapped at the current depth?
*/
if (existing_mapping != null
&& existing_mapping.m_declarationDepth == m_elemContext.m_currentElemDepth
&& !existing_mapping.m_uri.equals(uri))
{
/*
* There is an existing mapping of this prefix,
* it differs from the one we need,
* and unfortunately it is at the current depth so we
* can not over-ride it.
*/
/*
* Are we lucky enough that an existing other prefix maps to this URI ?
*/
prefix = m_prefixMap.lookupPrefix(uri);
if (prefix == null)
{
/* Unfortunately there is no existing prefix that happens to map to ours,
* so to avoid a prefix collision we must generated a new prefix to use.
* This is OK because the prefix URI mapping
* defined in the xsl:attribute is short in scope,
* just the xsl:attribute element itself,
* and at this point in serialization the body of the
* xsl:attribute, if any, is just a String. Right?
* . . . I sure hope so - Brian M.
*/
prefix = m_prefixMap.generateNextPrefix();
}
rawName = prefix + ':" + localName;
}
}
try
{
/* This is our last chance to make sure the namespace for this
* attribute is declared, especially if we just generated an alternate
* prefix to avoid a collision (the new prefix/rawName will go out of scope
* soon and be lost ... last chance here.
*/
String prefixUsed =
ensureAttributesNamespaceIsDeclared(
uri,
localName,
rawName);
}
catch (SAXException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
m_attributes.addAttribute(uri, localName, rawName, type, value);
was_added = true;
if (m_tracer != null){
firePseudoAttributes();
}
}
return was_added;
}
Adds the given attribute to the set of attributes, even if there is
no currently open element. This is useful if a SAX startPrefixMapping()
should need to add an attribute before the element name is seen.
This method is a copy of its super classes method, except that some
tracing of events is done. This is so the tracing is only done for
stream serializers, not for SAX ones. |
public void attributeDecl(String eName,
String aName,
String type,
String valueDefault,
String value) throws SAXException {
// Do not inline external DTD
if (m_inExternalDTD)
return;
try
{
final java.io.Writer writer = m_writer;
DTDprolog();
writer.write("< !ATTLIST ");
writer.write(eName);
writer.write(' ");
writer.write(aName);
writer.write(' ");
writer.write(type);
if (valueDefault != null)
{
writer.write(' ");
writer.write(valueDefault);
}
//writer.write(" ");
//writer.write(value);
writer.write(' >");
writer.write(m_lineSep, 0, m_lineSepLen);
}
catch (IOException e)
{
throw new SAXException(e);
}
}
Report an attribute type declaration.
Only the effective (first) declaration for an attribute will
be reported. The type will be one of the strings "CDATA",
"ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
"ENTITIES", or "NOTATION", or a parenthesized token group with
the separator "|" and all whitespace removed. |
protected void cdata(char[] ch,
int start,
int length) throws SAXException {
try
{
final int old_start = start;
if (m_elemContext.m_startTagOpen)
{
closeStartTag();
m_elemContext.m_startTagOpen = false;
}
m_ispreserve = true;
if (shouldIndent())
indent();
boolean writeCDataBrackets =
(((length >= 1) && escapingNotNeeded(ch[start])));
/* Write out the CDATA opening delimiter only if
* we are supposed to, and if we are not already in
* the middle of a CDATA section
*/
if (writeCDataBrackets && !m_cdataTagOpen)
{
m_writer.write(CDATA_DELIMITER_OPEN);
m_cdataTagOpen = true;
}
// writer.write(ch, start, length);
if (isEscapingDisabled())
{
charactersRaw(ch, start, length);
}
else
writeNormalizedChars(ch, start, length, true, m_lineSepUse);
/* used to always write out CDATA closing delimiter here,
* but now we delay, so that we can merge CDATA sections on output.
* need to write closing delimiter later
*/
if (writeCDataBrackets)
{
/* if the CDATA section ends with ] don't leave it open
* as there is a chance that an adjacent CDATA sections
* starts with ] >.
* We don't want to merge ]] with > , or ] with ] >
*/
if (ch[start + length - 1] == ']")
closeCDATA();
}
// time to fire off CDATA event
if (m_tracer != null)
super.fireCDATAEvent(ch, old_start, length);
}
catch (IOException ioe)
{
throw new org.xml.sax.SAXException(
Utils.messages.createMessage(
MsgKey.ER_OIERROR,
null),
ioe);
//"IO error", ioe);
}
}
Receive notification of cdata.
The Parser will call this method to report each chunk of
character data. SAX parsers may return all contiguous character
data in a single chunk, or they may split it into several
chunks; however, all of the characters in any single event
must come from the same external entity, so that the Locator
provides useful information.
The application must not attempt to read from the array
outside of the specified range.
Note that some parsers will report whitespace using the
ignorableWhitespace() method rather than this one (validating
parsers must do so). |
public void characters(String s) throws SAXException {
if (m_inEntityRef && !m_expandDTDEntities)
return;
final int length = s.length();
if (length > m_charsBuff.length)
{
m_charsBuff = new char[length * 2 + 1];
}
s.getChars(0, length, m_charsBuff, 0);
characters(m_charsBuff, 0, length);
}
Receive notification of character data. |
public void characters(char[] chars,
int start,
int length) throws SAXException {
// It does not make sense to continue with rest of the method if the number of
// characters to read from array is 0.
// Section 7.6.1 of XSLT 1.0 (http://www.w3.org/TR/xslt#value-of) suggest no text node
// is created if string is empty.
if (length == 0 || (m_inEntityRef && !m_expandDTDEntities))
return;
if (m_elemContext.m_startTagOpen)
{
closeStartTag();
m_elemContext.m_startTagOpen = false;
}
else if (m_needToCallStartDocument)
{
startDocumentInternal();
}
if (m_cdataStartCalled || m_elemContext.m_isCdataSection)
{
/* either due to startCDATA() being called or due to
* cdata-section-elements atribute, we need this as cdata
*/
cdata(chars, start, length);
return;
}
if (m_cdataTagOpen)
closeCDATA();
// the check with _escaping is a bit of a hack for XLSTC
if (m_disableOutputEscapingStates.peekOrFalse() || (!m_escaping))
{
charactersRaw(chars, start, length);
// time to fire off characters generation event
if (m_tracer != null)
super.fireCharEvent(chars, start, length);
return;
}
if (m_elemContext.m_startTagOpen)
{
closeStartTag();
m_elemContext.m_startTagOpen = false;
}
try
{
int i;
char ch1;
int startClean;
// skip any leading whitspace
// don't go off the end and use a hand inlined version
// of isWhitespace(ch)
final int end = start + length;
int lastDirty = start - 1; // last character that needed processing
for (i = start;
((i < end)
&& ((ch1 = chars[i]) == 0x20
|| (ch1 == 0xA && m_lineSepUse)
|| ch1 == 0xD
|| ch1 == 0x09));
i++)
{
/*
* We are processing leading whitespace, but are doing the same
* processing for dirty characters here as for non-whitespace.
*
*/
if (!m_charInfo.isTextASCIIClean(ch1))
{
lastDirty = processDirty(chars,end, i,ch1, lastDirty, true);
i = lastDirty;
}
}
/* If there is some non-whitespace, mark that we may need
* to preserve this. This is only important if we have indentation on.
*/
if (i < end)
m_ispreserve = true;
// int lengthClean; // number of clean characters in a row
// final boolean[] isAsciiClean = m_charInfo.getASCIIClean();
final boolean isXML10 = XMLVERSION10.equals(getVersion());
// we've skipped the leading whitespace, now deal with the rest
for (; i < end; i++)
{
{
// A tight loop to skip over common clean chars
// This tight loop makes it easier for the JIT
// to optimize.
char ch2;
while (i< end
&& ((ch2 = chars[i])< 127)
&& m_charInfo.isTextASCIIClean(ch2))
i++;
if (i == end)
break;
}
final char ch = chars[i];
/* The check for isCharacterInC0orC1Ranger and
* isNELorLSEPCharacter has been added
* to support Control Characters in XML 1.1
*/
if (!isCharacterInC0orC1Range(ch) &&
(isXML10 || !isNELorLSEPCharacter(ch)) &&
(escapingNotNeeded(ch) && (!m_charInfo.isSpecialTextChar(ch)))
|| ('"" == ch))
{
; // a character needing no special processing
}
else
{
lastDirty = processDirty(chars,end, i, ch, lastDirty, true);
i = lastDirty;
}
}
// we've reached the end. Any clean characters at the
// end of the array than need to be written out?
startClean = lastDirty + 1;
if (i > startClean)
{
int lengthClean = i - startClean;
m_writer.write(chars, startClean, lengthClean);
}
// For indentation purposes, mark that we've just writen text out
m_isprevtext = true;
}
catch (IOException e)
{
throw new SAXException(e);
}
// time to fire off characters generation event
if (m_tracer != null)
super.fireCharEvent(chars, start, length);
}
Receive notification of character data.
The Parser will call this method to report each chunk of
character data. SAX parsers may return all contiguous character
data in a single chunk, or they may split it into several
chunks; however, all of the characters in any single event
must come from the same external entity, so that the Locator
provides useful information.
The application must not attempt to read from the array
outside of the specified range.
Note that some parsers will report whitespace using the
ignorableWhitespace() method rather than this one (validating
parsers must do so). |
protected void charactersRaw(char[] ch,
int start,
int length) throws SAXException {
if (m_inEntityRef)
return;
try
{
if (m_elemContext.m_startTagOpen)
{
closeStartTag();
m_elemContext.m_startTagOpen = false;
}
m_ispreserve = true;
m_writer.write(ch, start, length);
}
catch (IOException e)
{
throw new SAXException(e);
}
}
If available, when the disable-output-escaping attribute is used,
output raw text without escaping. |
protected void closeCDATA() throws SAXException {
try
{
m_writer.write(CDATA_DELIMITER_CLOSE);
// write out a CDATA section closing "]] >"
m_cdataTagOpen = false; // Remember that we have done so.
}
catch (IOException e)
{
throw new SAXException(e);
}
}
This helper method to writes out "]]>" when closing a CDATA section. |
protected void closeStartTag() throws SAXException {
if (m_elemContext.m_startTagOpen)
{
try
{
if (m_tracer != null)
super.fireStartElem(m_elemContext.m_elementName);
int nAttrs = m_attributes.getLength();
if (nAttrs > 0)
{
processAttributes(m_writer, nAttrs);
// clear attributes object for re-use with next element
m_attributes.clear();
}
m_writer.write(' >");
}
catch (IOException e)
{
throw new SAXException(e);
}
/* whether Xalan or XSLTC, we have the prefix mappings now, so
* lets determine if the current element is specified in the cdata-
* section-elements list.
*/
if (m_cdataSectionElements != null)
m_elemContext.m_isCdataSection = isCdataSection();
if (m_doIndent)
{
m_isprevtext = false;
m_preserves.push(m_ispreserve);
}
}
}
For the enclosing elements starting tag write out
out any attributes followed by ">" |
public void comment(char[] ch,
int start,
int length) throws SAXException {
int start_old = start;
if (m_inEntityRef)
return;
if (m_elemContext.m_startTagOpen)
{
closeStartTag();
m_elemContext.m_startTagOpen = false;
}
else if (m_needToCallStartDocument)
{
startDocumentInternal();
m_needToCallStartDocument = false;
}
try
{
if (shouldIndent())
indent();
final int limit = start + length;
boolean wasDash = false;
if (m_cdataTagOpen)
closeCDATA();
final java.io.Writer writer = m_writer;
writer.write(COMMENT_BEGIN);
// Detect occurrences of two consecutive dashes, handle as necessary.
for (int i = start; i < limit; i++)
{
if (wasDash && ch[i] == '-")
{
writer.write(ch, start, i - start);
writer.write(" -");
start = i + 1;
}
wasDash = (ch[i] == '-");
}
// if we have some chars in the comment
if (length > 0)
{
// Output the remaining characters (if any)
final int remainingChars = (limit - start);
if (remainingChars > 0)
writer.write(ch, start, remainingChars);
// Protect comment end from a single trailing dash
if (ch[limit - 1] == '-")
writer.write(' ");
}
writer.write(COMMENT_END);
}
catch (IOException e)
{
throw new SAXException(e);
}
m_startNewLine = true;
// time to generate comment event
if (m_tracer != null)
super.fireCommentEvent(ch, start_old,length);
}
Receive notification of an XML comment anywhere in the document. This
callback will be used for comments inside or outside the document
element, including comments in the external DTD subset (if read). |
public void elementDecl(String name,
String model) throws SAXException {
// Do not inline external DTD
if (m_inExternalDTD)
return;
try
{
final java.io.Writer writer = m_writer;
DTDprolog();
writer.write("< !ELEMENT ");
writer.write(name);
writer.write(' ");
writer.write(model);
writer.write(' >");
writer.write(m_lineSep, 0, m_lineSepLen);
}
catch (IOException e)
{
throw new SAXException(e);
}
}
Report an element type declaration.
The content model will consist of the string "EMPTY", the
string "ANY", or a parenthesised group, optionally followed
by an occurrence indicator. The model will be normalized so
that all whitespace is removed,and will include the enclosing
parentheses. |
public void endCDATA() throws SAXException {
if (m_cdataTagOpen)
closeCDATA();
m_cdataStartCalled = false;
}
Report the end of a CDATA section. |
public void endDTD() throws SAXException {
try
{
// Don't output doctype declaration until startDocumentInternal
// has been called. Otherwise, it can appear before XML decl.
if (m_needToCallStartDocument) {
return;
}
if (m_needToOutputDocTypeDecl)
{
outputDocTypeDecl(m_elemContext.m_elementName, false);
m_needToOutputDocTypeDecl = false;
}
final java.io.Writer writer = m_writer;
if (!m_inDoctype)
writer.write("] >");
else
{
writer.write(' >");
}
writer.write(m_lineSep, 0, m_lineSepLen);
}
catch (IOException e)
{
throw new SAXException(e);
}
}
Report the end of DTD declarations. |
public void endElement(String name) throws SAXException {
endElement(null, null, name);
}
Receive notification of the end of an element. |
public void endElement(String namespaceURI,
String localName,
String name) throws SAXException {
if (m_inEntityRef)
return;
// namespaces declared at the current depth are no longer valid
// so get rid of them
m_prefixMap.popNamespaces(m_elemContext.m_currentElemDepth, null);
try
{
final java.io.Writer writer = m_writer;
if (m_elemContext.m_startTagOpen)
{
if (m_tracer != null)
super.fireStartElem(m_elemContext.m_elementName);
int nAttrs = m_attributes.getLength();
if (nAttrs > 0)
{
processAttributes(m_writer, nAttrs);
// clear attributes object for re-use with next element
m_attributes.clear();
}
if (m_spaceBeforeClose)
writer.write(" / >");
else
writer.write("/ >");
/* don't need to pop cdataSectionState because
* this element ended so quickly that we didn't get
* to push the state.
*/
}
else
{
if (m_cdataTagOpen)
closeCDATA();
if (shouldIndent())
indent(m_elemContext.m_currentElemDepth - 1);
writer.write('< ");
writer.write('/");
writer.write(name);
writer.write(' >");
}
}
catch (IOException e)
{
throw new SAXException(e);
}
if (!m_elemContext.m_startTagOpen && m_doIndent)
{
m_ispreserve = m_preserves.isEmpty() ? false : m_preserves.pop();
}
m_isprevtext = false;
// fire off the end element event
if (m_tracer != null)
super.fireEndElem(name);
m_elemContext = m_elemContext.m_prev;
}
Receive notification of the end of an element. |
public void endNonEscaping() throws SAXException {
m_disableOutputEscapingStates.pop();
}
Ends an un-escaping section. |
public void endPrefixMapping(String prefix) throws SAXException {
// do nothing
}
End the scope of a prefix-URI Namespace mapping. |
protected String ensureAttributesNamespaceIsDeclared(String ns,
String localName,
String rawName) throws SAXException {
if (ns != null && ns.length() > 0)
{
// extract the prefix in front of the raw name
int index = 0;
String prefixFromRawName =
(index = rawName.indexOf(":")) < 0
? ""
: rawName.substring(0, index);
if (index > 0)
{
// we have a prefix, lets see if it maps to a namespace
String uri = m_prefixMap.lookupNamespace(prefixFromRawName);
if (uri != null && uri.equals(ns))
{
// the prefix in the raw name is already maps to the given namespace uri
// so we don't need to do anything
return null;
}
else
{
// The uri does not map to the prefix in the raw name,
// so lets make the mapping.
this.startPrefixMapping(prefixFromRawName, ns, false);
this.addAttribute(
"http://www.w3.org/2000/xmlns/",
prefixFromRawName,
"xmlns:" + prefixFromRawName,
"CDATA",
ns, false);
return prefixFromRawName;
}
}
else
{
// we don't have a prefix in the raw name.
// Does the URI map to a prefix already?
String prefix = m_prefixMap.lookupPrefix(ns);
if (prefix == null)
{
// uri is not associated with a prefix,
// so lets generate a new prefix to use
prefix = m_prefixMap.generateNextPrefix();
this.startPrefixMapping(prefix, ns, false);
this.addAttribute(
"http://www.w3.org/2000/xmlns/",
prefix,
"xmlns:" + prefix,
"CDATA",
ns, false);
}
return prefix;
}
}
return null;
}
Makes sure that the namespace URI for the given qualified attribute name
is declared. |
void ensurePrefixIsDeclared(String ns,
String rawName) throws SAXException {
if (ns != null && ns.length() > 0)
{
int index;
final boolean no_prefix = ((index = rawName.indexOf(":")) < 0);
String prefix = (no_prefix) ? "" : rawName.substring(0, index);
if (null != prefix)
{
String foundURI = m_prefixMap.lookupNamespace(prefix);
if ((null == foundURI) || !foundURI.equals(ns))
{
this.startPrefixMapping(prefix, ns);
// Bugzilla1133: Generate attribute as well as namespace event.
// SAX does expect both.
this.addAttributeAlways(
"http://www.w3.org/2000/xmlns/",
no_prefix ? "xmlns" : prefix, // local name
no_prefix ? "xmlns" : ("xmlns:"+ prefix), // qname
"CDATA",
ns,
false);
}
}
}
}
|
protected boolean escapingNotNeeded(char ch) {
final boolean ret;
if (ch < 127)
{
// This is the old/fast code here, but is this
// correct for all encodings?
if (ch >= 0x20 || (0x0A == ch || 0x0D == ch || 0x09 == ch))
ret= true;
else
ret = false;
}
else {
ret = m_encodingInfo.isInEncoding(ch);
}
return ret;
}
Tell if this character can be written without escaping. |
public void externalEntityDecl(String name,
String publicId,
String systemId) throws SAXException {
try {
DTDprolog();
m_writer.write("< !ENTITY ");
m_writer.write(name);
if (publicId != null) {
m_writer.write(" PUBLIC \"");
m_writer.write(publicId);
}
else {
m_writer.write(" SYSTEM \"");
m_writer.write(systemId);
}
m_writer.write("\" >");
m_writer.write(m_lineSep, 0, m_lineSepLen);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
|
protected void firePseudoAttributes() {
if (m_tracer != null)
{
try
{
// flush out the "< elemName" if not already flushed
m_writer.flush();
// make a StringBuffer to write the name="value" pairs to.
StringBuffer sb = new StringBuffer();
int nAttrs = m_attributes.getLength();
if (nAttrs > 0)
{
// make a writer that internally appends to the same
// StringBuffer
java.io.Writer writer =
new ToStream.WritertoStringBuffer(sb);
processAttributes(writer, nAttrs);
// Don't clear the attributes!
// We only want to see what would be written out
// at this point, we don't want to loose them.
}
sb.append(' >"); // the potential > after the attributes.
// convert the StringBuffer to a char array and
// emit the trace event that these characters "might"
// be written
char ch[] = sb.toString().toCharArray();
m_tracer.fireGenerateEvent(
SerializerTrace.EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS,
ch,
0,
ch.length);
}
catch (IOException ioe)
{
// ignore ?
}
catch (SAXException se)
{
// ignore ?
}
}
}
To fire off the pseudo characters of attributes, as they currently
exist. This method should be called everytime an attribute is added,
or when an attribute value is changed, or an element is created. |
public void flushPending() throws SAXException {
if (m_needToCallStartDocument)
{
startDocumentInternal();
m_needToCallStartDocument = false;
}
if (m_elemContext.m_startTagOpen)
{
closeStartTag();
m_elemContext.m_startTagOpen = false;
}
if (m_cdataTagOpen)
{
closeCDATA();
m_cdataTagOpen = false;
}
}
This method flushes any pending events, which can be startDocument()
closing the opening tag of an element, or closing an open CDATA section. |
protected final void flushWriter() throws SAXException {
final java.io.Writer writer = m_writer;
if (null != writer)
{
try
{
if (writer instanceof WriterToUTF8Buffered)
{
if (m_shouldFlush)
((WriterToUTF8Buffered) writer).flush();
else
((WriterToUTF8Buffered) writer).flushBuffer();
}
if (writer instanceof WriterToASCI)
{
if (m_shouldFlush)
writer.flush();
}
else
{
// Flush always.
// Not a great thing if the writer was created
// by this class, but don't have a choice.
writer.flush();
}
}
catch (IOException ioe)
{
throw new org.xml.sax.SAXException(ioe);
}
}
}
Flush the formatter's result stream. |
public int getIndentAmount() {
return m_indentAmount;
}
Returns the m_indentAmount. |
public Properties getOutputFormat() {
return m_format;
}
Returns the output format for this serializer. |
public OutputStream getOutputStream() {
if (m_writer instanceof WriterToUTF8Buffered)
return ((WriterToUTF8Buffered) m_writer).getOutputStream();
if (m_writer instanceof WriterToASCI)
return ((WriterToASCI) m_writer).getOutputStream();
else
return null;
}
Get the output stream where the events will be serialized to. |
public Writer getWriter() {
return m_writer;
}
Get the character stream where the events will be serialized to. |
public void ignorableWhitespace(char[] ch,
int start,
int length) throws SAXException {
if (0 == length)
return;
characters(ch, start, length);
}
Receive notification of ignorable whitespace in element content.
Not sure how to get this invoked quite yet. |
protected void indent() throws IOException {
indent(m_elemContext.m_currentElemDepth);
}
Indent at the current element nesting depth. |
protected void indent(int depth) throws IOException {
if (m_startNewLine)
outputLineSep();
/* For m_indentAmount > 0 this extra test might be slower
* but Xalan's default value is 0, so this extra test
* will run faster in that situation.
*/
if (m_indentAmount > 0)
printSpace(depth * m_indentAmount);
}
Might print a newline character and the indentation amount
of the given depth. |
protected synchronized void init(OutputStream output,
Properties format,
boolean defaultProperties) throws UnsupportedEncodingException {
String encoding = getEncoding();
if (encoding == null)
{
// if not already set then get it from the properties
encoding =
Encodings.getMimeEncoding(
format.getProperty(OutputKeys.ENCODING));
setEncoding(encoding);
}
if (encoding.equalsIgnoreCase("UTF-8"))
{
m_isUTF8 = true;
// if (output instanceof java.io.BufferedOutputStream)
// {
// init(new WriterToUTF8(output), format, defaultProperties, true);
// }
// else if (output instanceof java.io.FileOutputStream)
// {
// init(new WriterToUTF8Buffered(output), format, defaultProperties, true);
// }
// else
// {
// // Not sure what to do in this case. I'm going to be conservative
// // and not buffer.
// init(new WriterToUTF8(output), format, defaultProperties, true);
// }
init(
new WriterToUTF8Buffered(output),
format,
defaultProperties,
true);
}
else if (
encoding.equals("WINDOWS-1250")
|| encoding.equals("US-ASCII")
|| encoding.equals("ASCII"))
{
init(new WriterToASCI(output), format, defaultProperties, true);
}
else
{
Writer osw;
try
{
osw = Encodings.getWriter(output, encoding);
}
catch (UnsupportedEncodingException uee)
{
System.out.println(
"Warning: encoding \""
+ encoding
+ "\" not supported"
+ ", using "
+ Encodings.DEFAULT_MIME_ENCODING);
encoding = Encodings.DEFAULT_MIME_ENCODING;
setEncoding(encoding);
osw = Encodings.getWriter(output, encoding);
}
init(osw, format, defaultProperties, true);
}
}
Initialize the serializer with the specified output stream and output
format. Must be called before calling any of the serialize methods. |
public void internalEntityDecl(String name,
String value) throws SAXException {
// Do not inline external DTD
if (m_inExternalDTD)
return;
try
{
DTDprolog();
outputEntityDecl(name, value);
}
catch (IOException e)
{
throw new SAXException(e);
}
}
|
static final boolean isUTF16Surrogate(char c) {
return (c & 0xFC00) == 0xD800;
}
Return true if the character is the high member of a surrogate pair.
NEEDSDOC @param c
NEEDSDOC ($objectName$) @return |
public void notationDecl(String name,
String pubID,
String sysID) throws SAXException {
// TODO Auto-generated method stub
try {
DTDprolog();
m_writer.write("< !NOTATION ");
m_writer.write(name);
if (pubID != null) {
m_writer.write(" PUBLIC \"");
m_writer.write(pubID);
}
else {
m_writer.write(" SYSTEM \"");
m_writer.write(sysID);
}
m_writer.write("\" >");
m_writer.write(m_lineSep, 0, m_lineSepLen);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
If this method is called, the serializer is used as a
DTDHandler, which changes behavior how the serializer
handles document entities. |
void outputDocTypeDecl(String name,
boolean closeDecl) throws SAXException {
if (m_cdataTagOpen)
closeCDATA();
try
{
final java.io.Writer writer = m_writer;
writer.write("< !DOCTYPE ");
writer.write(name);
String doctypePublic = getDoctypePublic();
if (null != doctypePublic)
{
writer.write(" PUBLIC \"");
writer.write(doctypePublic);
writer.write('\"");
}
String doctypeSystem = getDoctypeSystem();
if (null != doctypeSystem)
{
if (null == doctypePublic)
writer.write(" SYSTEM \"");
else
writer.write(" \"");
writer.write(doctypeSystem);
if (closeDecl)
{
writer.write("\" >");
writer.write(m_lineSep, 0, m_lineSepLen);
closeDecl = false; // done closing
}
else
writer.write('\"");
}
boolean dothis = false;
if (dothis)
{
// at one point this code seemed right,
// but not anymore - Brian M.
if (closeDecl)
{
writer.write(' >");
writer.write(m_lineSep, 0, m_lineSepLen);
}
}
}
catch (IOException e)
{
throw new SAXException(e);
}
}
Output the doc type declaration. |
void outputEntityDecl(String name,
String value) throws IOException {
final java.io.Writer writer = m_writer;
writer.write("< !ENTITY ");
writer.write(name);
writer.write(" \"");
writer.write(value);
writer.write("\" >");
writer.write(m_lineSep, 0, m_lineSepLen);
}
Output the doc type declaration. |
protected final void outputLineSep() throws IOException {
m_writer.write(m_lineSep, 0, m_lineSepLen);
}
Output a system-dependent line break. |
public void processAttributes(Writer writer,
int nAttrs) throws IOException, SAXException {
/* real SAX attributes are not passed in, so process the
* attributes that were collected after the startElement call.
* _attribVector is a "cheap" list for Stream serializer output
* accumulated over a series of calls to attribute(name,value)
*/
String encoding = getEncoding();
for (int i = 0; i < nAttrs; i++)
{
// elementAt is JDK 1.1.8
final String name = m_attributes.getQName(i);
final String value = m_attributes.getValue(i);
writer.write(' ");
writer.write(name);
writer.write("=\"");
writeAttrString(writer, value, encoding);
writer.write('\"");
}
}
Process the attributes, which means to write out the currently
collected attributes to the writer. The attributes are not
cleared by this method |
public boolean reset() {
boolean wasReset = false;
if (super.reset())
{
resetToStream();
wasReset = true;
}
return wasReset;
}
Try's to reset the super class and reset this class for
re-use, so that you don't need to create a new serializer
(mostly for performance reasons). |
public void serialize(Node node) throws IOException {
try
{
TreeWalker walker =
new TreeWalker(this);
walker.traverse(node);
}
catch (org.xml.sax.SAXException se)
{
throw new WrappedRuntimeException(se);
}
}
Serializes the DOM node. Throws an exception only if an I/O
exception occured while serializing. |
public void setCdataSectionElements(Vector URI_and_localNames) {
m_cdataSectionElements = URI_and_localNames;
}
Remembers the cdata sections specified in the cdata-section-elements.
The "official way to set URI and localName pairs.
This method should be used by both Xalan and XSLTC. |
public void setContentHandler(ContentHandler ch) {
// this method is really only useful in the ToSAXHandler classes but it is
// in the interface. If the method defined here is ever called
// we are probably in trouble.
}
|
public void setDTDEntityExpansion(boolean expand) {
m_expandDTDEntities = expand;
}
If set to false the serializer does not expand DTD entities,
but leaves them as is, the default value is true; |
public void setEncoding(String encoding) {
String old = getEncoding();
super.setEncoding(encoding);
if (old == null || !old.equals(encoding)) {
// If we have changed the setting of the
m_encodingInfo = Encodings.getEncodingInfo(encoding);
if (encoding != null && m_encodingInfo.name == null) {
// We tried to get an EncodingInfo for Object for the given
// encoding, but it came back with an internall null name
// so the encoding is not supported by the JDK, issue a message.
String msg = Utils.messages.createMessage(
MsgKey.ER_ENCODING_NOT_SUPPORTED,new Object[]{ encoding });
try
{
// Prepare to issue the warning message
Transformer tran = super.getTransformer();
if (tran != null) {
ErrorListener errHandler = tran.getErrorListener();
// Issue the warning message
if (null != errHandler && m_sourceLocator != null)
errHandler.warning(new TransformerException(msg, m_sourceLocator));
else
System.out.println(msg);
}
else
System.out.println(msg);
}
catch (Exception e){}
}
}
return;
}
Sets the character encoding coming from the xsl:output encoding stylesheet attribute. |
public boolean setEscaping(boolean escape) {
final boolean temp = m_escaping;
m_escaping = escape;
return temp;
}
|
public void setIndentAmount(int m_indentAmount) {
this.m_indentAmount = m_indentAmount;
}
|
public boolean setLineSepUse(boolean use_sytem_line_break) {
boolean oldValue = m_lineSepUse;
m_lineSepUse = use_sytem_line_break;
return oldValue;
}
Set if the operating systems end-of-line line separator should
be used when serializing. If set false NL character
(decimal 10) is left alone, otherwise the new-line will be replaced on
output with the systems line separator. For example on UNIX this is
NL, while on Windows it is two characters, CR NL, where CR is the
carriage-return (decimal 13). |
public void setOutputFormat(Properties format) {
boolean shouldFlush = m_shouldFlush;
init(m_writer, format, false, false);
m_shouldFlush = shouldFlush;
}
Specifies an output format for this serializer. It the
serializer has already been associated with an output format,
it will switch to the new format. This method should not be
called while the serializer is in the process of serializing
a document. |
public void setOutputStream(OutputStream output) {
try
{
Properties format;
if (null == m_format)
format =
OutputPropertiesFactory.getDefaultMethodProperties(
Method.XML);
else
format = m_format;
init(output, format, true);
}
catch (UnsupportedEncodingException uee)
{
// Should have been warned in init, I guess...
}
}
Specifies an output stream to which the document should be
serialized. This method should not be called while the
serializer is in the process of serializing a document.
The encoding specified in the output properties is used, or
if no encoding was specified, the default for the selected
output method. |
public void setTransformer(Transformer transformer) {
super.setTransformer(transformer);
if (m_tracer != null
&& !(m_writer instanceof SerializerTraceWriter) )
m_writer = new SerializerTraceWriter(m_writer, m_tracer);
}
|
public void setWriter(Writer writer) {
// if we are tracing events we need to trace what
// characters are written to the output writer.
if (m_tracer != null
&& !(writer instanceof SerializerTraceWriter) )
m_writer = new SerializerTraceWriter(writer, m_tracer);
else
m_writer = writer;
}
Specifies a writer to which the document should be serialized.
This method should not be called while the serializer is in
the process of serializing a document. |
protected boolean shouldIndent() {
return m_doIndent && (!m_ispreserve && !m_isprevtext);
}
Tell if, based on space preservation constraints and the doIndent property,
if an indent should occur. |
public void skippedEntity(String name) throws SAXException {
// TODO: Should handle
}
Receive notification of a skipped entity. |
public void startCDATA() throws SAXException {
m_cdataStartCalled = true;
}
Report the start of a CDATA section. |
public void startDTD(String name,
String publicId,
String systemId) throws SAXException {
setDoctypeSystem(systemId);
setDoctypePublic(publicId);
m_elemContext.m_elementName = name;
m_inDoctype = true;
}
Report the start of DTD declarations, if any.
Any declarations are assumed to be in the internal subset unless
otherwise indicated. |
public void startElement(String elementName) throws SAXException {
startElement(null, null, elementName, null);
}
|
public void startElement(String elementNamespaceURI,
String elementLocalName,
String elementName) throws SAXException {
startElement(elementNamespaceURI, elementLocalName, elementName, null);
}
Receive notification of the beginning of an element, additional
namespace or attribute information can occur before or after this call,
that is associated with this element. |
public void startElement(String namespaceURI,
String localName,
String name,
Attributes atts) throws SAXException {
if (m_inEntityRef)
return;
if (m_needToCallStartDocument)
{
startDocumentInternal();
m_needToCallStartDocument = false;
}
else if (m_cdataTagOpen)
closeCDATA();
try
{
if ((true == m_needToOutputDocTypeDecl)
&& (null != getDoctypeSystem()))
{
outputDocTypeDecl(name, true);
}
m_needToOutputDocTypeDecl = false;
/* before we over-write the current elementLocalName etc.
* lets close out the old one (if we still need to)
*/
if (m_elemContext.m_startTagOpen)
{
closeStartTag();
m_elemContext.m_startTagOpen = false;
}
if (namespaceURI != null)
ensurePrefixIsDeclared(namespaceURI, name);
m_ispreserve = false;
if (shouldIndent() && m_startNewLine)
{
indent();
}
m_startNewLine = true;
final java.io.Writer writer = m_writer;
writer.write('< ");
writer.write(name);
}
catch (IOException e)
{
throw new SAXException(e);
}
// process the attributes now, because after this SAX call they might be gone
if (atts != null)
addAttributes(atts);
m_elemContext = m_elemContext.push(namespaceURI,localName,name);
m_isprevtext = false;
if (m_tracer != null){
firePseudoAttributes();
}
}
Receive notification of the beginning of an element, although this is a
SAX method additional namespace or attribute information can occur before
or after this call, that is associated with this element. |
public void startEntity(String name) throws SAXException {
if (name.equals("[dtd]"))
m_inExternalDTD = true;
if (!m_expandDTDEntities && !m_inExternalDTD) {
/* Only leave the entity as-is if
* we've been told not to expand them
* and this is not the magic [dtd] name.
*/
startNonEscaping();
characters("&" + name + ';");
endNonEscaping();
}
m_inEntityRef = true;
}
Report the beginning of an entity.
The start and end of the document entity are not reported.
The start and end of the external DTD subset are reported
using the pseudo-name "[dtd]". All other events must be
properly nested within start/end entity events. |
public void startNonEscaping() throws SAXException {
m_disableOutputEscapingStates.push(true);
}
|
public void startPrefixMapping(String prefix,
String uri) throws SAXException {
// the "true" causes the flush of any open tags
startPrefixMapping(prefix, uri, true);
}
Begin the scope of a prefix-URI Namespace mapping
just before another element is about to start.
This call will close any open tags so that the prefix mapping
will not apply to the current element, but the up comming child. |
public boolean startPrefixMapping(String prefix,
String uri,
boolean shouldFlush) throws SAXException {
/* Remember the mapping, and at what depth it was declared
* This is one greater than the current depth because these
* mappings will apply to the next depth. This is in
* consideration that startElement() will soon be called
*/
boolean pushed;
int pushDepth;
if (shouldFlush)
{
flushPending();
// the prefix mapping applies to the child element (one deeper)
pushDepth = m_elemContext.m_currentElemDepth + 1;
}
else
{
// the prefix mapping applies to the current element
pushDepth = m_elemContext.m_currentElemDepth;
}
pushed = m_prefixMap.pushNamespace(prefix, uri, pushDepth);
if (pushed)
{
/* Brian M.: don't know if we really needto do this. The
* callers of this object should have injected both
* startPrefixMapping and the attributes. We are
* just covering our butt here.
*/
String name;
if (EMPTYSTRING.equals(prefix))
{
name = "xmlns";
addAttributeAlways(XMLNS_URI, name, name, "CDATA", uri, false);
}
else
{
if (!EMPTYSTRING.equals(uri))
// hack for XSLTC attribset16 test
{ // that maps ns1 prefix to "" URI
name = "xmlns:" + prefix;
/* for something like xmlns:abc="w3.pretend.org"
* the uri is the value, that is why we pass it in the
* value, or 5th slot of addAttributeAlways()
*/
addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri, false);
}
}
}
return pushed;
}
Handle a prefix/uri mapping, which is associated with a startElement()
that is soon to follow. Need to close any open start tag to make
sure than any name space attributes due to this event are associated wih
the up comming element, not the current one. |
public void unparsedEntityDecl(String name,
String pubID,
String sysID,
String notationName) throws SAXException {
// TODO Auto-generated method stub
try {
DTDprolog();
m_writer.write("< !ENTITY ");
m_writer.write(name);
if (pubID != null) {
m_writer.write(" PUBLIC \"");
m_writer.write(pubID);
}
else {
m_writer.write(" SYSTEM \"");
m_writer.write(sysID);
}
m_writer.write("\" NDATA ");
m_writer.write(notationName);
m_writer.write(" >");
m_writer.write(m_lineSep, 0, m_lineSepLen);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
If this method is called, the serializer is used as a
DTDHandler, which changes behavior how the serializer
handles document entities. |
public void writeAttrString(Writer writer,
String string,
String encoding) throws IOException {
final int len = string.length();
if (len > m_attrBuff.length)
{
m_attrBuff = new char[len*2 + 1];
}
string.getChars(0,len, m_attrBuff, 0);
final char[] stringChars = m_attrBuff;
for (int i = 0; i < len; )
{
char ch = stringChars[i];
if (escapingNotNeeded(ch) && (!m_charInfo.isSpecialAttrChar(ch)))
{
writer.write(ch);
i++;
}
else
{ // I guess the parser doesn't normalize cr/lf in attributes. -sb
// if ((CharInfo.S_CARRIAGERETURN == ch)
// && ((i + 1) < len)
// && (CharInfo.S_LINEFEED == stringChars[i + 1]))
// {
// i++;
// ch = CharInfo.S_LINEFEED;
// }
i = accumDefaultEscape(writer, ch, i, stringChars, len, false, true);
}
}
}
Returns the specified string after substituting specials,
and UTF-16 surrogates for chracter references &#xnn. |
void writeNormalizedChars(char[] ch,
int start,
int length,
boolean isCData,
boolean useSystemLineSeparator) throws IOException, SAXException {
final java.io.Writer writer = m_writer;
int end = start + length;
for (int i = start; i < end; i++)
{
char c = ch[i];
if (CharInfo.S_LINEFEED == c && useSystemLineSeparator)
{
writer.write(m_lineSep, 0, m_lineSepLen);
}
else if (isCData && (!escapingNotNeeded(c)))
{
// if (i != 0)
if (m_cdataTagOpen)
closeCDATA();
// This needs to go into a function...
if (Encodings.isHighUTF16Surrogate(c))
{
writeUTF16Surrogate(c, ch, i, end);
i++ ; // process two input characters
}
else
{
writer.write("");
String intStr = Integer.toString((int) c);
writer.write(intStr);
writer.write(';");
}
// if ((i != 0) && (i < (end - 1)))
// if (!m_cdataTagOpen && (i < (end - 1)))
// {
// writer.write(CDATA_DELIMITER_OPEN);
// m_cdataTagOpen = true;
// }
}
else if (
isCData
&& ((i < (end - 2))
&& (']" == c)
&& (']" == ch[i + 1])
&& (' >" == ch[i + 2])))
{
writer.write(CDATA_CONTINUE);
i += 2;
}
else
{
if (escapingNotNeeded(c))
{
if (isCData && !m_cdataTagOpen)
{
writer.write(CDATA_DELIMITER_OPEN);
m_cdataTagOpen = true;
}
writer.write(c);
}
// This needs to go into a function...
else if (Encodings.isHighUTF16Surrogate(c))
{
if (m_cdataTagOpen)
closeCDATA();
writeUTF16Surrogate(c, ch, i, end);
i++; // process two input characters
}
else
{
if (m_cdataTagOpen)
closeCDATA();
writer.write("");
String intStr = Integer.toString((int) c);
writer.write(intStr);
writer.write(';");
}
}
}
}
Normalize the characters, but don't escape. |
protected int writeUTF16Surrogate(char c,
char[] ch,
int i,
int end) throws IOException {
int codePoint = 0;
if (i + 1 >= end)
{
throw new IOException(
Utils.messages.createMessage(
MsgKey.ER_INVALID_UTF16_SURROGATE,
new Object[] { Integer.toHexString((int) c)}));
}
final char high = c;
final char low = ch[i+1];
if (!Encodings.isLowUTF16Surrogate(low)) {
throw new IOException(
Utils.messages.createMessage(
MsgKey.ER_INVALID_UTF16_SURROGATE,
new Object[] {
Integer.toHexString((int) c)
+ " "
+ Integer.toHexString(low)}));
}
final java.io.Writer writer = m_writer;
// If we make it to here we have a valid high, low surrogate pair
if (m_encodingInfo.isInEncoding(c,low)) {
// If the character formed by the surrogate pair
// is in the encoding, so just write it out
writer.write(ch,i,2);
}
else {
// Don't know what to do with this char, it is
// not in the encoding and not a high char in
// a surrogate pair, so write out as an entity ref
final String encoding = getEncoding();
if (encoding != null) {
/* The output encoding is known,
* so somthing is wrong.
*/
codePoint = Encodings.toCodePoint(high, low);
// not in the encoding, so write out a character reference
writer.write('&");
writer.write('#");
writer.write(Integer.toString(codePoint));
writer.write(';");
} else {
/* The output encoding is not known,
* so just write it out as-is.
*/
writer.write(ch, i, 2);
}
}
// non-zero only if character reference was written out.
return codePoint;
}
Once a surrogate has been detected, write out the pair of
characters if it is in the encoding, or if there is no
encoding, otherwise write out an entity reference
of the value of the unicode code point of the character
represented by the high/low surrogate pair.
An exception is thrown if there is no low surrogate in the pair,
because the array ends unexpectely, or if the low char is there
but its value is such that it is not a low surrogate. |