KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > output > GeneralOutputter


1 package com.icl.saxon.output;
2 import com.icl.saxon.*;
3 import com.icl.saxon.charcode.*;
4 import com.icl.saxon.om.NamePool;
5 import com.icl.saxon.om.NodeInfo;
6 import com.icl.saxon.om.DocumentInfo;
7 import com.icl.saxon.om.Builder;
8 import com.icl.saxon.tree.AttributeCollection;
9 import com.icl.saxon.tree.TreeBuilder;
10 import com.icl.saxon.tree.DocumentImpl;
11 import com.icl.saxon.tinytree.TinyBuilder;
12 //import com.icl.saxon.tinytree.TinyDocumentImpl;
13
import org.xml.sax.Attributes JavaDoc;
14 import org.w3c.dom.Node JavaDoc;
15 import org.w3c.dom.Document JavaDoc;
16 import java.util.Properties JavaDoc;
17 import javax.xml.transform.TransformerException JavaDoc;
18 import javax.xml.transform.Result JavaDoc;
19 import javax.xml.transform.OutputKeys JavaDoc;
20 import javax.xml.transform.stream.StreamResult JavaDoc;
21 import javax.xml.transform.dom.DOMResult JavaDoc;
22 import javax.xml.transform.sax.SAXResult JavaDoc;
23 import java.io.*;
24
25 /**
26   * This class allows output to be generated. It channels output requests to an
27   * Emitter which does the actual writing.
28   *
29   * @author <A HREF="mailto:mhkay@iclway.co.uk>Michael H. Kay</A>
30   */

31
32   
33
34 public class GeneralOutputter extends Outputter {
35
36     private NamePool namePool;
37     private Properties JavaDoc outputProperties;
38     private Writer writer;
39     private OutputStream outputStream;
40     private boolean closeAfterUse = false;
41     
42     private int pendingStartTag = -1;
43     private AttributeCollection pendingAttList;
44     
45     private int[] pendingNSList = new int[20];
46     private int pendingNSListSize = 0;
47     
48     private boolean suppressAttributes = false;
49
50     public GeneralOutputter(NamePool pool) {
51         namePool = pool;
52         pendingAttList = new AttributeCollection(namePool, 10);
53     }
54
55     /**
56     * Initialise the outputter for a new output destination, supplying
57     * the output format details. <BR>
58     * @param outputProperties Details of the new output format
59     * @param result Details of the new output destination
60     */

61
62     public void setOutputDestination(Properties JavaDoc props, Result JavaDoc result)
63     throws TransformerException JavaDoc {
64         setOutputProperties(props);
65         
66         Emitter emitter = makeEmitter(props, result);
67         emitter.setNamePool(namePool);
68         emitter.setOutputProperties(props);
69                 
70         setEmitter(emitter);
71
72         open();
73     }
74
75     /**
76     * The following atrocious code is borrowed from Xalan, where it is commented simply:
77     * // yuck.
78     * The backslash variants added by MHK.
79     */

80     
81     public static String JavaDoc urlToFileName(String JavaDoc base) {
82         if(null != base) {
83             if (base.startsWith("file:////")) {
84                 base = base.substring(7);
85             } else if (base.startsWith("file:///")) {
86                 base = base.substring(6);
87             } else if (base.startsWith("file://")) {
88                 base = base.substring(5); // absolute?
89
} else if (base.startsWith("file:/")) {
90                 base = base.substring(5);
91             } else if (base.startsWith("file:")) {
92                 base = base.substring(4);
93             } if (base.startsWith("file:\\\\\\\\")) {
94                 base = base.substring(7);
95             } else if (base.startsWith("file:\\\\\\")) {
96                 base = base.substring(6);
97             } else if (base.startsWith("file:\\\\")) {
98                 base = base.substring(5);
99             } else if (base.startsWith("file:\\")) {
100                 base = base.substring(5);
101             }
102         }
103         if (File.separatorChar != '/') {
104             base = base.replace('/', File.separatorChar);
105         }
106         return base;
107     }
108
109     /**
110     * Create a new FileOutputStream, given a filename and a baseURI
111     */

112    
113     public static FileOutputStream makeFileOutputStream( String JavaDoc baseURI,
114                                                     String JavaDoc fileName,
115                                                     boolean mkdirs)
116     throws TransformerException JavaDoc
117     {
118         try {
119             File file = new File(fileName);
120     
121             if (!file.isAbsolute()) {
122                 String JavaDoc base = urlToFileName(baseURI);
123                 if(null != base) {
124                     File baseFile = new File(base);
125                     file = new File(baseFile.getParent(), fileName);
126                 }
127             }
128     
129             if (mkdirs) {
130                 String JavaDoc dirStr = file.getParent();
131                 if((null != dirStr) && (dirStr.length() > 0)) {
132                     File dir = new File(dirStr);
133                     dir.mkdirs();
134                 }
135             }
136     
137             FileOutputStream ostream = new FileOutputStream(file);
138             return ostream;
139         } catch (Exception JavaDoc err) {
140             throw new TransformerException JavaDoc("Failed to create output file", err);
141         }
142   }
143
144
145     /**
146     * Make an emitter appropriate for a given set of output properties and
147     * output destination. Also updates the output properties
148     */

149
150     public Emitter makeEmitter(Properties JavaDoc props, Result JavaDoc result)
151     throws TransformerException JavaDoc {
152               
153         Emitter emitter;
154         if (result instanceof DOMResult JavaDoc) {
155             Node JavaDoc resultNode = ((DOMResult JavaDoc)result).getNode();
156             if (resultNode!=null) {
157                 if (resultNode instanceof NodeInfo) {
158                     // Writing to a SAXON tree is handled specially
159
if (resultNode instanceof DocumentInfo) {
160                         DocumentInfo doc = (DocumentInfo)resultNode;
161                         if (resultNode.getFirstChild() != null) {
162                             throw new TransformerException JavaDoc("Target document must be empty");
163                         } else {
164                             Builder builder;
165                             if (doc instanceof DocumentImpl) {
166                                 builder = new TreeBuilder();
167                             } else {
168                                 builder = new TinyBuilder();
169                             }
170                             builder.setRootNode(doc);
171                             builder.setSystemId(result.getSystemId());
172                             builder.setNamePool(namePool);
173                             emitter = builder;
174                         }
175                     } else {
176                         throw new TransformerException JavaDoc("Cannot add to an existing Saxon document");
177                     }
178                 } else {
179                     // Non-Saxon DOM
180
emitter = new DOMEmitter();
181                     ((DOMEmitter)emitter).setNode(resultNode);
182                 }
183             } else {
184                 // no result node supplied; we must create our own
185
TinyBuilder builder = new TinyBuilder();
186                 builder.setSystemId(result.getSystemId());
187                 builder.setNamePool(namePool);
188                 builder.createDocument();
189                 Document JavaDoc resultDoc = (Document JavaDoc)builder.getCurrentDocument();
190                 ((DOMResult JavaDoc)result).setNode(resultDoc);
191                 emitter = builder;
192             }
193         } else if (result instanceof SAXResult JavaDoc) {
194             SAXResult JavaDoc sr = (SAXResult JavaDoc)result;
195             ContentHandlerProxy proxy = new ContentHandlerProxy();
196             proxy.setUnderlyingContentHandler(sr.getHandler());
197             if (sr.getLexicalHandler() != null) {
198                 proxy.setLexicalHandler(sr.getLexicalHandler());
199             }
200             emitter = proxy;
201             
202         } else if (result instanceof Emitter) {
203             emitter = (Emitter)result;
204             
205         } else if (result instanceof StreamResult JavaDoc) {
206         
207             String JavaDoc method = props.getProperty(OutputKeys.METHOD);
208             if (method==null) {
209                 emitter = new UncommittedEmitter();
210                 
211             } else if (method.equals("html")) {
212                 emitter = new HTMLEmitter();
213                 if (!"no".equals(props.getProperty(OutputKeys.INDENT))) {
214                     HTMLIndenter in = new HTMLIndenter();
215                     in.setUnderlyingEmitter(emitter);
216                     emitter=in;
217                 }
218
219             } else if (method.equals("xml")) {
220                 emitter = new XMLEmitter();
221                 if ("yes".equals(props.getProperty(OutputKeys.INDENT))) {
222                     XMLIndenter in = new XMLIndenter();
223                     in.setUnderlyingEmitter(emitter);
224                     emitter=in;
225                 }
226                 String JavaDoc cdataElements = props.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS);
227                 if (cdataElements!=null && cdataElements.length()>0) {
228                     CDATAFilter filter = new CDATAFilter();
229                     filter.setUnderlyingEmitter(emitter);
230                     emitter=filter;
231                 }
232             } else if (method.equals("text")) {
233                 emitter = new TEXTEmitter();
234     
235             } else {
236                 // TODO: externally supplied properties must be validated
237
int brace = method.indexOf('}');
238                 String JavaDoc localName = method.substring(brace+1);
239                 int colon = localName.indexOf(':');
240                 localName = localName.substring(colon+1);
241                 
242                 if (localName.equals("fop")) {
243                     // avoid an explicit external reference to avoid build problems
244
// when FOP is not present on the class path
245
emitter = Emitter.makeEmitter("com.icl.saxon.fop.FOPEmitter");
246                 } else if (localName.equals("xhtml")) {
247                     emitter = new XHTMLEmitter();
248                     if ("yes".equals(props.getProperty(OutputKeys.INDENT))) {
249                         HTMLIndenter in = new HTMLIndenter();
250                         in.setUnderlyingEmitter(emitter);
251                         emitter=in;
252                     }
253                     String JavaDoc cdataElements = props.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS);
254                     if (cdataElements!=null && cdataElements.length()>0) {
255                         CDATAFilter filter = new CDATAFilter();
256                         filter.setUnderlyingEmitter(emitter);
257                         emitter=filter;
258                     }
259                 } else {
260                     emitter = Emitter.makeEmitter(localName);
261                 }
262             }
263             if (emitter.usesWriter()) {
264                 writer = getStreamWriter((StreamResult JavaDoc)result, props);
265                 emitter.setWriter(writer);
266             } else {
267                 outputStream = getOutputStream((StreamResult JavaDoc)result, props);
268                 emitter.setOutputStream(outputStream);
269             }
270         
271         } else {
272             throw new IllegalArgumentException JavaDoc("Unknown type of Result: " + result.getClass());
273         }
274
275         // add a filter to remove duplicate namespaces
276
NamespaceEmitter ne = new NamespaceEmitter();
277         ne.setUnderlyingEmitter(emitter);
278         emitter = ne;
279         return emitter;
280     }
281
282     /**
283     * Get a Writer corresponding to the requested Result destination
284     */

285
286     private Writer getStreamWriter(StreamResult JavaDoc result, Properties JavaDoc props)
287     throws TransformerException JavaDoc {
288             
289         closeAfterUse = false;
290         Writer writer = result.getWriter();
291         if (writer==null) {
292             OutputStream outputStream = ((StreamResult JavaDoc)result).getOutputStream();
293             if (outputStream == null) {
294                 String JavaDoc systemId = ((StreamResult JavaDoc)result).getSystemId();
295                 if (systemId == null) {
296                     outputStream = System.out;
297                 } else {
298                     outputStream = makeFileOutputStream("", urlToFileName(systemId), true);
299                     closeAfterUse = true;
300                 }
301             }
302             
303             CharacterSet charSet = CharacterSetFactory.getCharacterSet(props);
304             
305             String JavaDoc encoding = props.getProperty(OutputKeys.ENCODING);
306             if (encoding==null) encoding = "UTF8";
307             if (encoding.equalsIgnoreCase("utf-8")) encoding = "UTF8";
308                  // needed for Microsoft Java VM
309

310             if (charSet instanceof PluggableCharacterSet) {
311                 encoding = ((PluggableCharacterSet)charSet).getEncodingName();
312             }
313
314             while (true) {
315                 try {
316                     writer = new BufferedWriter(
317                                     new OutputStreamWriter(
318                                         outputStream, encoding));
319                     break;
320                 } catch (Exception JavaDoc err) {
321                     if (encoding.equalsIgnoreCase("UTF8")) {
322                         throw new TransformerException JavaDoc("Failed to create a UTF8 output writer");
323                     }
324                     System.err.println("Encoding " + encoding + " is not supported: using UTF8");
325                     encoding = "UTF8";
326                     charSet = new UnicodeCharacterSet();
327                     props.put(OutputKeys.ENCODING, "utf-8");
328                 }
329             }
330         } else {
331             // a writer was supplied by the user
332
// if the writer uses a known encoding, change the encoding in the XML declaration
333
// to match.
334

335             if (writer instanceof OutputStreamWriter) {
336                 String JavaDoc enc = ((OutputStreamWriter)writer).getEncoding();
337                 //System.err.println("User-supplied writer, encoding=" + enc);
338
props.put(OutputKeys.ENCODING, enc);
339             }
340         }
341         return writer;
342     }
343
344     /**
345     * Get an OutputStream corresponding to the requested Result destination
346     */

347
348     private OutputStream getOutputStream(StreamResult JavaDoc result, Properties JavaDoc props)
349     throws TransformerException JavaDoc {
350             
351         closeAfterUse = false;
352
353         OutputStream outputStream = ((StreamResult JavaDoc)result).getOutputStream();
354         if (outputStream == null) {
355             String JavaDoc systemId = ((StreamResult JavaDoc)result).getSystemId();
356             if (systemId == null) {
357                 outputStream = System.out;
358             } else {
359                 outputStream = makeFileOutputStream("", urlToFileName(systemId), true);
360                 closeAfterUse = true;
361             }
362         }
363         
364         if (outputStream==null) {
365             throw new TransformerException JavaDoc("This output method requires a binary output destination");
366         }
367         
368         return outputStream;
369     }
370
371         
372     /**
373     * Set the emitter that will deal with this output
374     */

375
376     private void setEmitter(Emitter handler) {
377         this.emitter = handler;
378     }
379    
380     public void reset() throws TransformerException JavaDoc {
381         if (pendingStartTag != -1) flushStartTag();
382     }
383
384     private void setOutputProperties(Properties JavaDoc details) throws TransformerException JavaDoc {
385         outputProperties = details;
386     }
387
388     public Properties JavaDoc getOutputProperties() {
389         return outputProperties;
390     }
391
392     /**
393     * Produce literal output. This is written as is, without any escaping.
394     * The method is provided for Java applications that wish to output literal HTML text.
395     * It is not used by the XSL system, which always writes using specific methods such as
396     * writeStartTag().
397     */

398
399     char[] charbuffer = new char[1024];
400     public void write(String JavaDoc s) throws TransformerException JavaDoc {
401         if (pendingStartTag != -1) flushStartTag();
402         emitter.setEscaping(false);
403         int len = s.length();
404         if (len>charbuffer.length) {
405             charbuffer = new char[len];
406         }
407         s.getChars(0, len, charbuffer, 0);
408         emitter.characters(charbuffer, 0, len);
409         emitter.setEscaping(true);
410     }
411
412     /**
413     * Produce text content output. <BR>
414     * Special characters are escaped using XML/HTML conventions if the output format
415     * requires it.
416     * @param s The String to be output
417     * @exception TransformerException for any failure
418     */

419
420     public void writeContent(String JavaDoc s) throws TransformerException JavaDoc {
421         if (s==null) return;
422         int len = s.length();
423         if (len>charbuffer.length) {
424             charbuffer = new char[len];
425         }
426         s.getChars(0, len, charbuffer, 0);
427         writeContent(charbuffer, 0, len);
428     }
429     
430     /**
431     * Produce text content output. <BR>
432     * Special characters are escaped using XML/HTML conventions if the output format
433     * requires it.
434     * @param chars Character array to be output
435     * @param start start position of characters to be output
436     * @param length number of characters to be output
437     * @exception TransformerException for any failure
438     */

439
440     public void writeContent(char[] chars, int start, int length) throws TransformerException JavaDoc {
441         //System.err.println("WriteContent " + this + ":" + new String(chars, start, length) );
442
if (length==0) return;
443         if (pendingStartTag != -1) {
444             flushStartTag();
445         }
446         emitter.characters(chars, start, length);
447     }
448
449     /**
450     * Produce text content output. <BR>
451     * Special characters are escaped using XML/HTML conventions if the output format
452     * requires it.
453     * @param chars StringBuffer containing to be output
454     * @param start start position of characters to be output
455     * @param len number of characters to be output
456     * @exception TransformerException for any failure
457     */

458
459     public void writeContent(StringBuffer JavaDoc chars, int start, int len) throws TransformerException JavaDoc {
460         //System.err.println("WriteContent " + this + ":" + chars.substring(start, start+length) );
461
if (len==0) return;
462         if (pendingStartTag != -1) {
463             flushStartTag();
464         }
465         if (len>charbuffer.length) {
466             charbuffer = new char[len];
467         }
468         chars.getChars(start, start+len, charbuffer, 0);
469         emitter.characters(charbuffer, 0, len);
470     }
471
472     /**
473     * Output an element start tag. <br>
474     * The actual output of the tag is deferred until all attributes have been output
475     * using writeAttribute().
476     * @param nameCode The element name code
477     */

478
479     public void writeStartTag(int nameCode) throws TransformerException JavaDoc {
480         // System.err.println("Write start tag " + this + " : " + nameCode + " to emitter " + emitter);
481

482         if (nameCode==-1) {
483             suppressAttributes = true;
484             return;
485         } else {
486             suppressAttributes = false;
487         }
488         
489         if (pendingStartTag != -1) flushStartTag();
490         pendingAttList.clear();
491         pendingNSListSize = 0;
492         pendingStartTag = nameCode;
493         
494         // make sure there is a namespace declaration for this start tag
495
//writeNamespaceDeclaration(namePool.allocateNamespaceCode(nameCode));
496
// ***** now done by the NamespaceEmitter
497
}
498
499     /**
500     * Check that the prefix for an attribute is acceptable, returning a substitute
501     * prefix if not. The prefix is acceptable unless a namespace declaration has been
502     * written that assignes this prefix to a different namespace URI. This method
503     * also checks that the attribute namespace has been declared, and declares it
504     * if not.
505     */

506     
507     public int checkAttributePrefix(int nameCode) throws TransformerException JavaDoc {
508         int nscode = namePool.allocateNamespaceCode(nameCode);
509         for (int i=0; i<pendingNSListSize; i++) {
510             if ((nscode>>16) == (pendingNSList[i]>>16)) {
511                 // same prefix
512
if ((nscode & 0xffff) == (pendingNSList[i] & 0xffff)) {
513                     // same URI
514
return nameCode; // all is well
515
} else {
516                     String JavaDoc prefix = getSubstitutePrefix(nscode);
517                     int newCode = namePool.allocate(
518                                         prefix,
519                                         namePool.getURI(nameCode),
520                                         namePool.getLocalName(nameCode));
521                     writeNamespaceDeclaration(namePool.allocateNamespaceCode(newCode));
522                     return newCode;
523                 }
524             }
525         }
526         // no declaration of this prefix: declare it now
527
writeNamespaceDeclaration(nscode);
528         return nameCode;
529     }
530             
531     /**
532     * Output a namespace declaration. <br>
533     * This is added to a list of pending namespaces for the current start tag.
534     * If there is already another declaration of the same prefix, this one is
535     * ignored.
536     * Note that unlike SAX2 startPrefixMapping(), this call is made AFTER writing the start tag.
537     * @param nscode The namespace code
538     * @throws TransformerException if there is no start tag to write to (created using writeStartTag),
539     * or if character content has been written since the start tag was written.
540     */

541
542     public void writeNamespaceDeclaration(int nscode)
543     throws TransformerException JavaDoc {
544
545         if (suppressAttributes) return;
546         
547         // System.err.println("Write namespace prefix=" + (nscode>>16) + " uri=" + (nscode&0xffff));
548
if (pendingStartTag==-1) {
549             throw new TransformerException JavaDoc("Cannot write a namespace declaration when there is no open start tag");
550         }
551
552         // elimination of namespaces already present on an outer element of the
553
// result tree is now done by the NamespaceEmitter.
554

555         // Ignore declarations whose prefix is duplicated for this element.
556

557         for (int i=0; i<pendingNSListSize; i++) {
558             if ((nscode>>16) == (pendingNSList[i]>>16)) {
559                 // same prefix, do a quick exit
560
return;
561             }
562         }
563
564         // if it's not a duplicate namespace, add it to the list for this start tag
565

566         if (pendingNSListSize+1 > pendingNSList.length) {
567             int[] newlist = new int[pendingNSListSize * 2];
568             System.arraycopy(pendingNSList, 0, newlist, 0, pendingNSListSize);
569             pendingNSList = newlist;
570         }
571         pendingNSList[pendingNSListSize++] = nscode;
572     }
573
574     /**
575     * Copy a namespace node to the current element node
576     * (Rules defined in XSLT 1.0 errata)
577     */

578     
579     public void copyNamespaceNode(int nscode) throws TransformerException JavaDoc {
580         if (pendingStartTag==-1) {
581             throw new TransformerException JavaDoc("Cannot copy a namespace node when there is no containing element node");
582         }
583         if (pendingAttList.getLength()>0) {
584             throw new TransformerException JavaDoc("Cannot copy a namespace node to an element after attributes have been added");
585         }
586         
587         // check for duplicates
588
for (int i=0; i<pendingNSListSize; i++) {
589             if ((nscode>>16) == (pendingNSList[i]>>16)) {
590                 // same prefix
591
if (nscode==pendingNSList[i]) { // same URI
592
return; // ignore the duplicate
593
} else {
594                     // may need to handle default namespace differently
595
throw new TransformerException JavaDoc("Cannot create two namespace nodes with the same name");
596                 }
597             }
598         }
599         writeNamespaceDeclaration(nscode);
600     }
601
602     /**
603     * It is possible for a single output element to use the same prefix to refer to different
604     * namespaces. In this case we have to generate an alternative prefix for uniqueness. The
605     * one we generate is based on the uri part of the namespace code itself,
606     * which is almost certain to be unique.
607     */

608
609     private String JavaDoc getSubstitutePrefix(int nscode) {
610         String JavaDoc prefix = namePool.getPrefixFromNamespaceCode(nscode);
611         return prefix + "." + (nscode&0xffff);
612     }
613
614     /**
615     * Test whether there is an open start tag. This determines whether it is
616     * possible to write an attribute node at this point.
617     */

618     
619     public boolean thereIsAnOpenStartTag() {
620         return (pendingStartTag != -1);
621     }
622     
623     /**
624     * Output an attribute value. <br>
625     * This is added to a list of pending attributes for the current start tag, overwriting
626     * any previous attribute with the same name. <br>
627     * This method should NOT be used to output namespace declarations.
628     * @param nameCode The name code of the attribute
629     * @param value The value of the attribute
630     * @throws TransformerException if there is no start tag to write to (created using writeStartTag),
631     * or if character content has been written since the start tag was written.
632     */

633
634     public void writeAttribute(int nameCode, String JavaDoc value) throws TransformerException JavaDoc {
635         writeAttribute(nameCode, value, false);
636     }
637
638     /**
639     * Output an attribute value. <br>
640     * This is added to a list of pending attributes for the current start tag, overwriting
641     * any previous attribute with the same name. <br>
642     * This method should NOT be used to output namespace declarations.<br>
643     * Before calling this, checkAttributePrefix() should be called to ensure the namespace
644     * is OK.
645     * @param name The name of the attribute
646     * @param value The value of the attribute
647     * @param noEscape True if it's known there are no special characters in the value. If
648     * unsure, set this to false.
649     * @throws TransformerException if there is no start tag to write to (created using writeStartTag),
650     * or if character content has been written since the start tag was written.
651     */

652
653     public void writeAttribute(int nameCode, String JavaDoc value, boolean noEscape) throws TransformerException JavaDoc {
654
655         if (suppressAttributes) return;
656
657         // System.err.println("Write attribute " + nameCode + "=" + value + " (" + noEscape + ") to Outputter " + this);
658
if (pendingStartTag==-1) {
659             throw new TransformerException JavaDoc("Cannot write an attribute when there is no open start tag");
660         }
661
662         pendingAttList.setAttribute(nameCode,
663               (noEscape ? "NO-ESC" : "CDATA"), // dummy attribute type to indicate no special chars
664
value);
665
666     }
667
668
669     /**
670     * Output an element end tag.<br>
671     * @param nameCode The element name code
672     */

673
674     public void writeEndTag(int nameCode) throws TransformerException JavaDoc {
675         //System.err.println("Write end tag " + this + " : " + name);
676
if (pendingStartTag != -1) {
677             flushStartTag();
678         }
679         
680         // write the end tag
681
emitter.endElement(nameCode);
682     }
683
684     /**
685     * Write a comment
686     */

687
688     public void writeComment(String JavaDoc comment) throws TransformerException JavaDoc {
689         if (pendingStartTag != -1) flushStartTag();
690         emitter.comment(comment.toCharArray(), 0, comment.length());
691     }
692
693     /**
694     * Write a processing instruction
695     */

696
697     public void writePI(String JavaDoc target, String JavaDoc data) throws TransformerException JavaDoc {
698         if (pendingStartTag != -1) flushStartTag();
699         emitter.processingInstruction(target, data);
700     }
701
702     /**
703     * Close the output
704     */

705
706     public void close() throws TransformerException JavaDoc {
707         // System.err.println("Close " + this + " using emitter " + emitter.getClass());
708
emitter.endDocument();
709         if (closeAfterUse) {
710             try {
711                 if (writer != null) {
712                     writer.close();
713                 }
714                 if (outputStream != null) {
715                     outputStream.close();
716                 }
717             } catch (java.io.IOException JavaDoc err) {
718                 throw new TransformerException JavaDoc(err);
719             }
720         }
721     }
722
723     /**
724     * Flush out a pending start tag
725     */

726
727     protected void flushStartTag() throws TransformerException JavaDoc {
728         emitter.startElement(pendingStartTag, pendingAttList,
729                                  pendingNSList, pendingNSListSize);
730         pendingNSListSize = 0;
731         pendingStartTag = -1;
732             
733     }
734
735 }
736
737 //
738
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
739
// you may not use this file except in compliance with the License. You may obtain a copy of the
740
// License at http://www.mozilla.org/MPL/
741
//
742
// Software distributed under the License is distributed on an "AS IS" basis,
743
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
744
// See the License for the specific language governing rights and limitations under the License.
745
//
746
// The Original Code is: all this file.
747
//
748
// The Initial Developer of the Original Code is
749
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
750
//
751
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
752
//
753
// Contributor(s): none.
754
//
755
Popular Tags