|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.sun.org.apache.xml.internal.serializer; |
|
|
|
import java.io.IOException; |
|
import java.io.OutputStream; |
|
import java.io.Writer; |
|
import java.util.Properties; |
|
|
|
import javax.xml.transform.Result; |
|
|
|
import org.w3c.dom.Node; |
|
import org.xml.sax.Attributes; |
|
import org.xml.sax.ContentHandler; |
|
import org.xml.sax.Locator; |
|
import org.xml.sax.SAXException; |
|
import org.xml.sax.ext.LexicalHandler; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class ToXMLSAXHandler extends ToSAXHandler |
|
{ |
|
|
|
|
|
|
|
*/ |
|
protected boolean m_escapeSetting = true; |
|
|
|
public ToXMLSAXHandler() |
|
{ |
|
|
|
m_prefixMap = new NamespaceMappings(); |
|
initCDATA(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Properties getOutputFormat() |
|
{ |
|
return null; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public OutputStream getOutputStream() |
|
{ |
|
return null; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Writer getWriter() |
|
{ |
|
return null; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void indent(int n) throws SAXException |
|
{ |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void serialize(Node node) throws IOException |
|
{ |
|
} |
|
|
|
|
|
|
|
*/ |
|
public boolean setEscaping(boolean escape) throws SAXException |
|
{ |
|
boolean oldEscapeSetting = m_escapeSetting; |
|
m_escapeSetting = escape; |
|
|
|
if (escape) { |
|
processingInstruction(Result.PI_ENABLE_OUTPUT_ESCAPING, ""); |
|
} else { |
|
processingInstruction(Result.PI_DISABLE_OUTPUT_ESCAPING, ""); |
|
} |
|
|
|
return oldEscapeSetting; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setOutputFormat(Properties format) |
|
{ |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setOutputStream(OutputStream output) |
|
{ |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setWriter(Writer writer) |
|
{ |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void attributeDecl( |
|
String arg0, |
|
String arg1, |
|
String arg2, |
|
String arg3, |
|
String arg4) |
|
throws SAXException |
|
{ |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void elementDecl(String arg0, String arg1) throws SAXException |
|
{ |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void externalEntityDecl(String arg0, String arg1, String arg2) |
|
throws SAXException |
|
{ |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void internalEntityDecl(String arg0, String arg1) |
|
throws SAXException |
|
{ |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void endDocument() throws SAXException |
|
{ |
|
|
|
flushPending(); |
|
|
|
|
|
m_saxHandler.endDocument(); |
|
|
|
if (m_tracer != null) |
|
super.fireEndDoc(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected void closeStartTag() throws SAXException |
|
{ |
|
|
|
m_elemContext.m_startTagOpen = false; |
|
|
|
final String localName = getLocalName(m_elemContext.m_elementName); |
|
final String uri = getNamespaceURI(m_elemContext.m_elementName, true); |
|
|
|
|
|
if (m_needToCallStartDocument) |
|
{ |
|
startDocumentInternal(); |
|
} |
|
m_saxHandler.startElement(uri, localName, m_elemContext.m_elementName, m_attributes); |
|
// we've sent the official SAX attributes on their way, |
|
|
|
m_attributes.clear(); |
|
|
|
if(m_state != null) |
|
m_state.setCurrentNode(null); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void closeCDATA() throws SAXException |
|
{ |
|
|
|
|
|
if (m_lexHandler != null && m_cdataTagOpen) { |
|
m_lexHandler.endCDATA(); |
|
} |
|
|
|
|
|
// There are no longer any calls made to |
|
// m_lexHandler.startCDATA() without a balancing call to |
|
// m_lexHandler.endCDATA() |
|
|
|
m_cdataTagOpen = false; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void endElement(String namespaceURI, String localName, String qName) |
|
throws SAXException |
|
{ |
|
|
|
flushPending(); |
|
|
|
if (namespaceURI == null) |
|
{ |
|
if (m_elemContext.m_elementURI != null) |
|
namespaceURI = m_elemContext.m_elementURI; |
|
else |
|
namespaceURI = getNamespaceURI(qName, true); |
|
} |
|
|
|
if (localName == null) |
|
{ |
|
if (m_elemContext.m_elementLocalName != null) |
|
localName = m_elemContext.m_elementLocalName; |
|
else |
|
localName = getLocalName(qName); |
|
} |
|
|
|
m_saxHandler.endElement(namespaceURI, localName, qName); |
|
|
|
if (m_tracer != null) |
|
super.fireEndElem(qName); |
|
|
|
|
|
|
|
*/ |
|
m_prefixMap.popNamespaces(m_elemContext.m_currentElemDepth, |
|
m_saxHandler); |
|
m_elemContext = m_elemContext.m_prev; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void endPrefixMapping(String prefix) throws SAXException |
|
{ |
|
|
|
|
|
*/ |
|
return; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void ignorableWhitespace(char[] arg0, int arg1, int arg2) |
|
throws SAXException |
|
{ |
|
m_saxHandler.ignorableWhitespace(arg0,arg1,arg2); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setDocumentLocator(Locator arg0) |
|
{ |
|
super.setDocumentLocator(arg0); |
|
m_saxHandler.setDocumentLocator(arg0); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void skippedEntity(String arg0) throws SAXException |
|
{ |
|
m_saxHandler.skippedEntity(arg0); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void startPrefixMapping(String prefix, String uri) |
|
throws SAXException |
|
{ |
|
startPrefixMapping(prefix, uri, true); |
|
} |
|
|
|
/** |
|
* Remember the prefix/uri mapping at the current nested element depth. |
|
* |
|
* @see org.xml.sax.ContentHandler#startPrefixMapping(String, String) |
|
* @param prefix The prefix that maps to the URI |
|
* @param uri The URI for the namespace |
|
* @param shouldFlush a flag indicating if the mapping applies to the |
|
* current element or an up coming child (not used). |
|
*/ |
|
|
|
public boolean startPrefixMapping( |
|
String prefix, |
|
String uri, |
|
boolean shouldFlush) |
|
throws org.xml.sax.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(); |
|
|
|
pushDepth = m_elemContext.m_currentElemDepth + 1; |
|
} |
|
else |
|
{ |
|
|
|
pushDepth = m_elemContext.m_currentElemDepth; |
|
} |
|
pushed = m_prefixMap.pushNamespace(prefix, uri, pushDepth); |
|
|
|
if (pushed) |
|
{ |
|
m_saxHandler.startPrefixMapping(prefix,uri); |
|
|
|
if (getShouldOutputNSAttr()) |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
String name; |
|
if (EMPTYSTRING.equals(prefix)) |
|
{ |
|
name = "xmlns"; |
|
addAttributeAlways(XMLNS_URI, name, name,"CDATA",uri, false); |
|
} |
|
else |
|
{ |
|
if (!EMPTYSTRING.equals(uri)) |
|
{ |
|
name = "xmlns:" + prefix; |
|
|
|
|
|
|
|
|
|
*/ |
|
addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri, false ); |
|
} |
|
} |
|
} |
|
} |
|
return pushed; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void comment(char[] arg0, int arg1, int arg2) throws SAXException |
|
{ |
|
flushPending(); |
|
if (m_lexHandler != null) |
|
m_lexHandler.comment(arg0, arg1, arg2); |
|
|
|
if (m_tracer != null) |
|
super.fireCommentEvent(arg0, arg1, arg2); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void endCDATA() throws SAXException |
|
{ |
|
/* Normally we would do somthing with this but we ignore it. |
|
* The neccessary call to m_lexHandler.endCDATA() will be made |
|
* in flushPending(). |
|
* |
|
* This is so that if we get calls like these: |
|
* this.startCDATA(); |
|
* this.characters(chars1, off1, len1); |
|
* this.endCDATA(); |
|
* this.startCDATA(); |
|
* this.characters(chars2, off2, len2); |
|
* this.endCDATA(); |
|
* |
|
* that we will only make these calls to the wrapped handlers: |
|
* |
|
* m_lexHandler.startCDATA(); |
|
* m_saxHandler.characters(chars1, off1, len1); |
|
* m_saxHandler.characters(chars1, off2, len2); |
|
* m_lexHandler.endCDATA(); |
|
* |
|
* We will merge adjacent CDATA blocks. |
|
*/ |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void endDTD() throws SAXException |
|
{ |
|
if (m_lexHandler != null) |
|
m_lexHandler.endDTD(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void startEntity(String arg0) throws SAXException |
|
{ |
|
if (m_lexHandler != null) |
|
m_lexHandler.startEntity(arg0); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void characters(String chars) throws SAXException |
|
{ |
|
final int length = chars.length(); |
|
if (length > m_charsBuff.length) |
|
{ |
|
m_charsBuff = new char[length*2 + 1]; |
|
} |
|
chars.getChars(0, length, m_charsBuff, 0); |
|
this.characters(m_charsBuff, 0, length); |
|
} |
|
|
|
|
|
public ToXMLSAXHandler(ContentHandler handler, String encoding) |
|
{ |
|
super(handler, encoding); |
|
|
|
initCDATA(); |
|
|
|
m_prefixMap = new NamespaceMappings(); |
|
} |
|
|
|
public ToXMLSAXHandler( |
|
ContentHandler handler, |
|
LexicalHandler lex, |
|
String encoding) |
|
{ |
|
super(handler, lex, encoding); |
|
|
|
initCDATA(); |
|
|
|
m_prefixMap = new NamespaceMappings(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void startElement( |
|
String elementNamespaceURI, |
|
String elementLocalName, |
|
String elementName) throws SAXException |
|
{ |
|
startElement( |
|
elementNamespaceURI,elementLocalName,elementName, null); |
|
|
|
|
|
} |
|
public void startElement(String elementName) throws SAXException |
|
{ |
|
startElement(null, null, elementName, null); |
|
} |
|
|
|
|
|
public void characters(char[] ch, int off, int len) throws SAXException |
|
{ |
|
// We do the first two things in flushPending() but we don't |
|
|
|
if (m_needToCallStartDocument) |
|
{ |
|
startDocumentInternal(); |
|
m_needToCallStartDocument = false; |
|
} |
|
|
|
if (m_elemContext.m_startTagOpen) |
|
{ |
|
closeStartTag(); |
|
m_elemContext.m_startTagOpen = false; |
|
} |
|
|
|
if (m_elemContext.m_isCdataSection && !m_cdataTagOpen |
|
&& m_lexHandler != null) |
|
{ |
|
m_lexHandler.startCDATA(); |
|
// We have made a call to m_lexHandler.startCDATA() with |
|
// no balancing call to m_lexHandler.endCDATA() |
|
|
|
m_cdataTagOpen = true; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
m_saxHandler.characters(ch, off, len); |
|
|
|
|
|
if (m_tracer != null) |
|
fireCharEvent(ch, off, len); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void endElement(String elemName) throws SAXException |
|
{ |
|
endElement(null, null, elemName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void namespaceAfterStartElement( |
|
final String prefix, |
|
final String uri) |
|
throws SAXException |
|
{ |
|
startPrefixMapping(prefix,uri,false); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void processingInstruction(String target, String data) |
|
throws SAXException |
|
{ |
|
flushPending(); |
|
|
|
|
|
m_saxHandler.processingInstruction(target, data); |
|
|
|
// we don't want to leave serializer to fire off this event, |
|
|
|
if (m_tracer != null) |
|
super.fireEscapingEvent(target, data); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected boolean popNamespace(String prefix) |
|
{ |
|
try |
|
{ |
|
if (m_prefixMap.popNamespace(prefix)) |
|
{ |
|
m_saxHandler.endPrefixMapping(prefix); |
|
return true; |
|
} |
|
} |
|
catch (SAXException e) |
|
{ |
|
// falls through |
|
} |
|
return false; |
|
} |
|
|
|
public void startCDATA() throws SAXException |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
if (!m_cdataTagOpen ) |
|
{ |
|
flushPending(); |
|
if (m_lexHandler != null) { |
|
m_lexHandler.startCDATA(); |
|
|
|
// We have made a call to m_lexHandler.startCDATA() with |
|
// no balancing call to m_lexHandler.endCDATA() |
|
|
|
m_cdataTagOpen = true; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void startElement( |
|
String namespaceURI, |
|
String localName, |
|
String name, |
|
Attributes atts) |
|
throws SAXException |
|
{ |
|
flushPending(); |
|
super.startElement(namespaceURI, localName, name, atts); |
|
|
|
|
|
if (m_needToOutputDocTypeDecl) |
|
{ |
|
String doctypeSystem = getDoctypeSystem(); |
|
if (doctypeSystem != null && m_lexHandler != null) |
|
{ |
|
String doctypePublic = getDoctypePublic(); |
|
if (doctypeSystem != null) |
|
m_lexHandler.startDTD( |
|
name, |
|
doctypePublic, |
|
doctypeSystem); |
|
} |
|
m_needToOutputDocTypeDecl = false; |
|
} |
|
m_elemContext = m_elemContext.push(namespaceURI, localName, name); |
|
|
|
// ensurePrefixIsDeclared depends on the current depth, so |
|
|
|
if (namespaceURI != null) |
|
ensurePrefixIsDeclared(namespaceURI, name); |
|
|
|
|
|
if (atts != null) |
|
addAttributes(atts); |
|
|
|
|
|
|
|
m_elemContext.m_isCdataSection = isCdataSection(); |
|
|
|
} |
|
|
|
private void ensurePrefixIsDeclared(String ns, String rawName) |
|
throws org.xml.sax.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, false); |
|
|
|
if (getShouldOutputNSAttr()) { |
|
// Bugzilla1133: Generate attribute as well as namespace event. |
|
|
|
this.addAttributeAlways( |
|
"http://www.w3.org/2000/xmlns/", |
|
no_prefix ? "xmlns" : prefix, |
|
no_prefix ? "xmlns" : ("xmlns:"+ prefix), |
|
"CDATA", |
|
ns, |
|
false); |
|
} |
|
} |
|
|
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void addAttribute( |
|
String uri, |
|
String localName, |
|
String rawName, |
|
String type, |
|
String value, |
|
boolean XSLAttribute) |
|
throws SAXException |
|
{ |
|
if (m_elemContext.m_startTagOpen) |
|
{ |
|
ensurePrefixIsDeclared(uri, rawName); |
|
addAttributeAlways(uri, localName, rawName, type, value, false); |
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean reset() |
|
{ |
|
boolean wasReset = false; |
|
if (super.reset()) |
|
{ |
|
resetToXMLSAXHandler(); |
|
wasReset = true; |
|
} |
|
return wasReset; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private void resetToXMLSAXHandler() |
|
{ |
|
this.m_escapeSetting = true; |
|
} |
|
|
|
} |