KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > ContentEmitter


1 package com.icl.saxon;
2 import com.icl.saxon.om.NamePool;
3 import com.icl.saxon.om.Name;
4 import com.icl.saxon.output.Emitter;
5
6 import org.xml.sax.*;
7 import org.xml.sax.ext.LexicalHandler JavaDoc;
8
9 import javax.xml.transform.TransformerException JavaDoc;
10
11 import java.net.URL JavaDoc;
12
13 /**
14   * ContentEmitter is a glue class that provides a standard SAX ContentHandler
15   * interface to a Saxon Emitter. To achieve this it needs to map names supplied
16   * as strings to numeric name codes, for which purpose it needs access to a name
17   * pool. The class also performs the function of assembling adjacent text nodes.
18   * @author Michael H. Kay (mhkay@iclway.co.uk)
19   */

20   
21 public class ContentEmitter implements ContentHandler, LexicalHandler JavaDoc, DTDHandler
22 {
23     private NamePool pool;
24     private Emitter emitter;
25     private boolean inDTD = false; // true while processing the DTD
26
private Locator locator;
27
28     // buffer for accumulating character data, until the next markup event is received
29

30     private char[] buffer = new char[4096];
31     private int used = 0;
32     
33     // array for accumulating namespace information
34

35     private int[] namespaces = new int[50];
36     private int namespacesUsed = 0;
37
38     /**
39     * create a ContentEmitter and initialise variables
40     */

41
42     public ContentEmitter() {
43     }
44
45     public void setEmitter(Emitter e) {
46         emitter = e;
47     }
48     
49     public void setNamePool(NamePool namePool) {
50         pool = namePool;
51     }
52
53     /**
54     * Callback interface for SAX: not for application use
55     */

56
57     public void startDocument () throws SAXException {
58         // System.err.println("ContentEmitter#startDocument");
59
try {
60             used = 0;
61             namespacesUsed = 0;
62             emitter.setDocumentLocator(locator);
63             emitter.startDocument();
64         } catch (TransformerException JavaDoc err) {
65             throw new SAXException(err);
66         }
67     }
68
69     /**
70     * Callback interface for SAX: not for application use
71     */

72
73     public void endDocument () throws SAXException {
74         try {
75             flush();
76             emitter.endDocument();
77         } catch (TransformerException JavaDoc err) {
78             throw new SAXException(err);
79         }
80     }
81
82     /**
83     * Callback interface for SAX: not for application use
84     */

85     
86     public void setDocumentLocator (Locator locator) {
87         this.locator = locator;
88         //emitter.setDocumentLocator(locator);
89
}
90
91     /**
92     * Callback interface for SAX: not for application use
93     */

94
95     public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri) /*throws SAXException*/ {
96         if (namespacesUsed >= namespaces.length) {
97             int[] n2 = new int[namespacesUsed * 2];
98             System.arraycopy(namespaces, 0, n2, 0, namespacesUsed);
99             namespaces = n2;
100         }
101         namespaces[namespacesUsed++] = pool.allocateNamespaceCode(prefix, uri);
102     }
103
104     /**
105     * Callback interface for SAX: not for application use
106     */

107
108     public void endPrefixMapping(String JavaDoc prefix) {}
109
110     /**
111     * Callback interface for SAX: not for application use
112     */

113
114     public void startElement (String JavaDoc uri, String JavaDoc localname, String JavaDoc rawname, Attributes atts)
115     throws SAXException
116     {
117         // System.err.println("ContentEmitter#startElement " + rawname);
118
try {
119             flush();
120             int nameCode = getNameCode(uri, localname, rawname);
121             emitter.startElement(nameCode, atts, namespaces, namespacesUsed);
122             namespacesUsed = 0;
123         } catch (TransformerException JavaDoc err) {
124             throw new SAXException(err);
125         }
126     }
127     
128     private int getNameCode(String JavaDoc uri, String JavaDoc localname, String JavaDoc rawname) {
129         String JavaDoc prefix = Name.getPrefix(rawname);
130         return pool.allocate(prefix, uri, localname);
131     }
132
133     /**
134     * Callback interface for SAX: not for application use
135     */

136
137     public void endElement (String JavaDoc uri, String JavaDoc localname, String JavaDoc rawname) throws SAXException {
138         try {
139             flush();
140             // TODO: it would be more efficient to maintain a stack of nameCodes
141
String JavaDoc prefix = Name.getPrefix(rawname);
142             int nameCode = pool.allocate(prefix, uri, localname);
143             emitter.endElement(nameCode);
144         } catch (TransformerException JavaDoc err) {
145             throw new SAXException(err);
146         }
147     }
148
149     /**
150     * Callback interface for SAX: not for application use
151     */

152
153     public void characters (char ch[], int start, int length) {
154         
155         // need to concatenate chunks of text before we can decide whether a node is all-white
156

157         while (used + length > buffer.length) {
158             char[] newbuffer = new char[buffer.length*2];
159             System.arraycopy(buffer, 0, newbuffer, 0, used);
160             buffer = newbuffer;
161         }
162         System.arraycopy(ch, start, buffer, used, length);
163         used += length;
164     }
165
166     /**
167     * Callback interface for SAX: not for application use
168     */

169  
170     public void ignorableWhitespace (char ch[], int start, int length) {
171         characters(ch, start, length);
172     }
173            
174     /**
175     * Callback interface for SAX: not for application use<BR>
176     */

177
178     public void processingInstruction (String JavaDoc name, String JavaDoc remainder) throws SAXException
179     {
180         try {
181             flush();
182             if (!inDTD) {
183                 if (name==null) {
184                     // trick used by some SAX1 parsers to notify a comment
185
comment(remainder.toCharArray(), 0, remainder.length());
186                 } else {
187                     // some parsers allow through PI names containing colons
188
if (!Name.isNCName(name)) {
189                         throw new SAXException("Invalid processing instruction name (" + name + ")");
190                     }
191                     emitter.processingInstruction(name, remainder);
192                 }
193             }
194         } catch (TransformerException JavaDoc err) {
195             throw new SAXException(err);
196         }
197     }
198
199     /**
200     * Callback interface for SAX (part of LexicalHandler interface): not for application use
201     */

202  
203     public void comment (char ch[], int start, int length) throws SAXException {
204         try {
205             flush();
206             if (!inDTD) {
207                 emitter.comment(ch, start, length);
208             }
209         } catch (TransformerException JavaDoc err) {
210             throw new SAXException(err);
211         }
212     }
213
214     /**
215     * Flush buffer for accumulated character data, suppressing white space if appropriate
216     */

217     
218     private void flush() throws TransformerException JavaDoc {
219         if (used > 0) {
220             emitter.characters(buffer, 0, used);
221             used = 0;
222         }
223     }
224
225     public void skippedEntity(String JavaDoc name) {}
226
227     // No-op methods to satisfy lexical handler interface
228

229     /**
230     * Register the start of the DTD. Comments in the DTD are skipped because they
231     * are not part of the XPath data model
232     */

233
234     public void startDTD (String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId) {
235         inDTD = true;
236     }
237
238     /**
239     * Register the end of the DTD. Comments in the DTD are skipped because they
240     * are not part of the XPath data model
241     */

242
243     public void endDTD () {
244         inDTD = false;
245     }
246
247     public void startEntity (String JavaDoc name) {};
248
249     public void endEntity (String JavaDoc name) {};
250
251     public void startCDATA () {};
252
253     public void endCDATA () {};
254
255     //////////////////////////////////////////////////////////////////////////////
256
// Implement DTDHandler interface
257
//////////////////////////////////////////////////////////////////////////////
258

259
260     public void notationDecl( String JavaDoc name,
261                                     String JavaDoc publicId,
262                                     String JavaDoc systemId)
263     {}
264
265
266     public void unparsedEntityDecl( String JavaDoc name,
267                                     String JavaDoc publicId,
268                                     String JavaDoc systemId,
269                                     String JavaDoc notationName) throws SAXException
270     {
271         //System.err.println("Unparsed entity " + name + "=" + systemId);
272

273         // Some SAX parsers report the systemId as written. We need to turn it into
274
// an absolute URL.
275

276         String JavaDoc uri = systemId;
277         if (locator!=null) {
278             try {
279                 String JavaDoc baseURI = locator.getSystemId();
280                 URL JavaDoc absoluteURI = new URL JavaDoc(new URL JavaDoc(baseURI), systemId);
281                 uri = absoluteURI.toString();
282             } catch (Exception JavaDoc err) {}
283         }
284         try {
285             emitter.setUnparsedEntity(name, uri);
286         } catch (TransformerException JavaDoc err) {
287             throw new SAXException(err);
288         }
289     }
290
291
292 } // end of class ContentEmitter
293

294 //
295
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
296
// you may not use this file except in compliance with the License. You may obtain a copy of the
297
// License at http://www.mozilla.org/MPL/
298
//
299
// Software distributed under the License is distributed on an "AS IS" basis,
300
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
301
// See the License for the specific language governing rights and limitations under the License.
302
//
303
// The Original Code is: all this file.
304
//
305
// The Initial Developer of the Original Code is
306
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
307
//
308
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
309
//
310
// Contributor(s): none.
311
//
312
Popular Tags