KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > trax > DOM2SAX


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: DOM2SAX.java,v 1.21 2004/02/16 22:57:21 minchau Exp $
18  */

19
20
21 package org.apache.xalan.xsltc.trax;
22
23 import java.io.IOException JavaDoc;
24 import java.util.Hashtable JavaDoc;
25 import java.util.Stack JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 import org.w3c.dom.NamedNodeMap JavaDoc;
29 import org.w3c.dom.Node JavaDoc;
30
31 import org.xml.sax.ContentHandler JavaDoc;
32 import org.xml.sax.DTDHandler JavaDoc;
33 import org.xml.sax.EntityResolver JavaDoc;
34 import org.xml.sax.ErrorHandler JavaDoc;
35 import org.xml.sax.InputSource JavaDoc;
36 import org.xml.sax.Locator JavaDoc;
37 import org.xml.sax.SAXException JavaDoc;
38 import org.xml.sax.SAXNotRecognizedException JavaDoc;
39 import org.xml.sax.SAXNotSupportedException JavaDoc;
40 import org.xml.sax.XMLReader JavaDoc;
41 import org.xml.sax.ext.LexicalHandler JavaDoc;
42 import org.xml.sax.helpers.AttributesImpl JavaDoc;
43 import org.apache.xalan.xsltc.dom.SAXImpl;
44
45 /**
46  * @author G. Todd Miller
47  */

48 public class DOM2SAX implements XMLReader JavaDoc, Locator JavaDoc {
49
50     private final static String JavaDoc EMPTYSTRING = "";
51     private static final String JavaDoc XMLNS_PREFIX = "xmlns";
52
53     private Node JavaDoc _dom = null;
54     private ContentHandler JavaDoc _sax = null;
55     private LexicalHandler JavaDoc _lex = null;
56     private SAXImpl _saxImpl = null;
57     private Hashtable JavaDoc _nsPrefixes = new Hashtable JavaDoc();
58
59     public DOM2SAX(Node JavaDoc root) {
60     _dom = root;
61     }
62
63     public ContentHandler JavaDoc getContentHandler() {
64     return _sax;
65     }
66
67     public void setContentHandler(ContentHandler JavaDoc handler) throws
68     NullPointerException JavaDoc
69     {
70     _sax = handler;
71     if (handler instanceof LexicalHandler JavaDoc) {
72         _lex = (LexicalHandler JavaDoc) handler;
73     }
74     
75     if (handler instanceof SAXImpl) {
76         _saxImpl = (SAXImpl)handler;
77     }
78     }
79
80     /**
81      * Begin the scope of namespace prefix. Forward the event to the
82      * SAX handler only if the prefix is unknown or it is mapped to a
83      * different URI.
84      */

85     private boolean startPrefixMapping(String JavaDoc prefix, String JavaDoc uri)
86     throws SAXException JavaDoc
87     {
88     boolean pushed = true;
89     Stack JavaDoc uriStack = (Stack JavaDoc) _nsPrefixes.get(prefix);
90
91     if (uriStack != null) {
92         if (uriStack.isEmpty()) {
93         _sax.startPrefixMapping(prefix, uri);
94         uriStack.push(uri);
95         }
96         else {
97         final String JavaDoc lastUri = (String JavaDoc) uriStack.peek();
98         if (!lastUri.equals(uri)) {
99             _sax.startPrefixMapping(prefix, uri);
100             uriStack.push(uri);
101         }
102         else {
103             pushed = false;
104         }
105         }
106     }
107     else {
108         _sax.startPrefixMapping(prefix, uri);
109         _nsPrefixes.put(prefix, uriStack = new Stack JavaDoc());
110         uriStack.push(uri);
111     }
112     return pushed;
113     }
114
115     /*
116      * End the scope of a name prefix by popping it from the stack and
117      * passing the event to the SAX Handler.
118      */

119     private void endPrefixMapping(String JavaDoc prefix)
120     throws SAXException JavaDoc
121     {
122     final Stack JavaDoc uriStack = (Stack JavaDoc) _nsPrefixes.get(prefix);
123
124     if (uriStack != null) {
125         _sax.endPrefixMapping(prefix);
126         uriStack.pop();
127     }
128     }
129
130     /**
131      * If the DOM was created using a DOM 1.0 API, the local name may be
132      * null. If so, get the local name from the qualified name before
133      * generating the SAX event.
134      */

135     private static String JavaDoc getLocalName(Node JavaDoc node) {
136     final String JavaDoc localName = node.getLocalName();
137
138     if (localName == null) {
139         final String JavaDoc qname = node.getNodeName();
140         final int col = qname.lastIndexOf(':');
141         return (col > 0) ? qname.substring(col + 1) : qname;
142     }
143     return localName;
144     }
145
146     public void parse(InputSource JavaDoc unused) throws IOException JavaDoc, SAXException JavaDoc {
147         parse(_dom);
148     }
149
150     public void parse() throws IOException JavaDoc, SAXException JavaDoc {
151     if (_dom != null) {
152         boolean isIncomplete =
153         (_dom.getNodeType() != org.w3c.dom.Node.DOCUMENT_NODE);
154
155         if (isIncomplete) {
156         _sax.startDocument();
157         parse(_dom);
158         _sax.endDocument();
159         }
160         else {
161         parse(_dom);
162         }
163     }
164     }
165
166     /**
167      * Traverse the DOM and generate SAX events for a handler. A
168      * startElement() event passes all attributes, including namespace
169      * declarations.
170      */

171     private void parse(Node JavaDoc node) throws IOException JavaDoc, SAXException JavaDoc {
172         Node JavaDoc first = null;
173     if (node == null) return;
174
175         switch (node.getNodeType()) {
176     case Node.ATTRIBUTE_NODE: // handled by ELEMENT_NODE
177
case Node.DOCUMENT_FRAGMENT_NODE:
178     case Node.DOCUMENT_TYPE_NODE :
179     case Node.ENTITY_NODE :
180     case Node.ENTITY_REFERENCE_NODE:
181     case Node.NOTATION_NODE :
182         // These node types are ignored!!!
183
break;
184     case Node.CDATA_SECTION_NODE:
185         final String JavaDoc cdata = node.getNodeValue();
186         if (_lex != null) {
187         _lex.startCDATA();
188             _sax.characters(cdata.toCharArray(), 0, cdata.length());
189         _lex.endCDATA();
190         }
191         else {
192         // in the case where there is no lex handler, we still
193
// want the text of the cdate to make its way through.
194
_sax.characters(cdata.toCharArray(), 0, cdata.length());
195         }
196         break;
197
198     case Node.COMMENT_NODE: // should be handled!!!
199
if (_lex != null) {
200         final String JavaDoc value = node.getNodeValue();
201         _lex.comment(value.toCharArray(), 0, value.length());
202         }
203         break;
204     case Node.DOCUMENT_NODE:
205         _sax.setDocumentLocator(this);
206
207         _sax.startDocument();
208         Node JavaDoc next = node.getFirstChild();
209         while (next != null) {
210         parse(next);
211         next = next.getNextSibling();
212         }
213         _sax.endDocument();
214         break;
215
216     case Node.ELEMENT_NODE:
217         String JavaDoc prefix;
218         Vector JavaDoc pushedPrefixes = new Vector JavaDoc();
219         final AttributesImpl JavaDoc attrs = new AttributesImpl JavaDoc();
220         final NamedNodeMap JavaDoc map = node.getAttributes();
221         final int length = map.getLength();
222
223         // Process all namespace declarations
224
for (int i = 0; i < length; i++) {
225         final Node JavaDoc attr = map.item(i);
226         final String JavaDoc qnameAttr = attr.getNodeName();
227
228         // Ignore everything but NS declarations here
229
if (qnameAttr.startsWith(XMLNS_PREFIX)) {
230             final String JavaDoc uriAttr = attr.getNodeValue();
231             final int colon = qnameAttr.lastIndexOf(':');
232             prefix = (colon > 0) ? qnameAttr.substring(colon + 1) : EMPTYSTRING;
233             if (startPrefixMapping(prefix, uriAttr)) {
234             pushedPrefixes.addElement(prefix);
235             }
236         }
237         }
238
239         // Process all other attributes
240
for (int i = 0; i < length; i++) {
241         final Node JavaDoc attr = map.item(i);
242         final String JavaDoc qnameAttr = attr.getNodeName();
243
244         // Ignore NS declarations here
245
if (!qnameAttr.startsWith(XMLNS_PREFIX)) {
246             final String JavaDoc uriAttr = attr.getNamespaceURI();
247             final String JavaDoc localNameAttr = getLocalName(attr);
248
249             // Uri may be implicitly declared
250
if (uriAttr != null) {
251             final int colon = qnameAttr.lastIndexOf(':');
252             prefix = (colon > 0) ? qnameAttr.substring(0, colon) : EMPTYSTRING;
253             if (startPrefixMapping(prefix, uriAttr)) {
254                 pushedPrefixes.addElement(prefix);
255             }
256             }
257
258             // Add attribute to list
259
attrs.addAttribute(attr.getNamespaceURI(), getLocalName(attr),
260             qnameAttr, "CDATA", attr.getNodeValue());
261         }
262         }
263
264         // Now process the element itself
265
final String JavaDoc qname = node.getNodeName();
266         final String JavaDoc uri = node.getNamespaceURI();
267         final String JavaDoc localName = getLocalName(node);
268
269         // Uri may be implicitly declared
270
if (uri != null) {
271         final int colon = qname.lastIndexOf(':');
272         prefix = (colon > 0) ? qname.substring(0, colon) : EMPTYSTRING;
273         if (startPrefixMapping(prefix, uri)) {
274             pushedPrefixes.addElement(prefix);
275         }
276         }
277
278         // Generate SAX event to start element
279
if (_saxImpl != null) {
280             _saxImpl.startElement(uri, localName, qname, attrs, node);
281         }
282         else {
283             _sax.startElement(uri, localName, qname, attrs);
284         }
285
286         // Traverse all child nodes of the element (if any)
287
next = node.getFirstChild();
288         while (next != null) {
289         parse(next);
290         next = next.getNextSibling();
291         }
292
293         // Generate SAX event to close element
294
_sax.endElement(uri, localName, qname);
295
296         // Generate endPrefixMapping() for all pushed prefixes
297
final int nPushedPrefixes = pushedPrefixes.size();
298         for (int i = 0; i < nPushedPrefixes; i++) {
299         endPrefixMapping((String JavaDoc) pushedPrefixes.elementAt(i));
300         }
301         break;
302
303     case Node.PROCESSING_INSTRUCTION_NODE:
304         _sax.processingInstruction(node.getNodeName(),
305                        node.getNodeValue());
306         break;
307
308     case Node.TEXT_NODE:
309         final String JavaDoc data = node.getNodeValue();
310         _sax.characters(data.toCharArray(), 0, data.length());
311         break;
312     }
313     }
314
315     /**
316      * This class is only used internally so this method should never
317      * be called.
318      */

319     public DTDHandler JavaDoc getDTDHandler() {
320     return null;
321     }
322
323     /**
324      * This class is only used internally so this method should never
325      * be called.
326      */

327     public ErrorHandler JavaDoc getErrorHandler() {
328     return null;
329     }
330
331     /**
332      * This class is only used internally so this method should never
333      * be called.
334      */

335     public boolean getFeature(String JavaDoc name) throws SAXNotRecognizedException JavaDoc,
336     SAXNotSupportedException JavaDoc
337     {
338     return false;
339     }
340
341     /**
342      * This class is only used internally so this method should never
343      * be called.
344      */

345     public void setFeature(String JavaDoc name, boolean value) throws
346     SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc
347     {
348     }
349
350     /**
351      * This class is only used internally so this method should never
352      * be called.
353      */

354     public void parse(String JavaDoc sysId) throws IOException JavaDoc, SAXException JavaDoc {
355     throw new IOException JavaDoc("This method is not yet implemented.");
356     }
357
358     /**
359      * This class is only used internally so this method should never
360      * be called.
361      */

362     public void setDTDHandler(DTDHandler JavaDoc handler) throws NullPointerException JavaDoc {
363     }
364
365     /**
366      * This class is only used internally so this method should never
367      * be called.
368      */

369     public void setEntityResolver(EntityResolver JavaDoc resolver) throws
370     NullPointerException JavaDoc
371     {
372     }
373
374     /**
375      * This class is only used internally so this method should never
376      * be called.
377      */

378     public EntityResolver JavaDoc getEntityResolver() {
379     return null;
380     }
381
382     /**
383      * This class is only used internally so this method should never
384      * be called.
385      */

386     public void setErrorHandler(ErrorHandler JavaDoc handler) throws
387     NullPointerException JavaDoc
388     {
389     }
390
391     /**
392      * This class is only used internally so this method should never
393      * be called.
394      */

395     public void setProperty(String JavaDoc name, Object JavaDoc value) throws
396     SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
397     }
398
399     /**
400      * This class is only used internally so this method should never
401      * be called.
402      */

403     public Object JavaDoc getProperty(String JavaDoc name) throws SAXNotRecognizedException JavaDoc,
404     SAXNotSupportedException JavaDoc
405     {
406     return null;
407     }
408
409     /**
410      * This class is only used internally so this method should never
411      * be called.
412      */

413     public int getColumnNumber() {
414     return 0;
415     }
416     
417     /**
418      * This class is only used internally so this method should never
419      * be called.
420      */

421     public int getLineNumber() {
422     return 0;
423     }
424
425     /**
426      * This class is only used internally so this method should never
427      * be called.
428      */

429     public String JavaDoc getPublicId() {
430     return null;
431     }
432
433     /**
434      * This class is only used internally so this method should never
435      * be called.
436      */

437     public String JavaDoc getSystemId() {
438     return null;
439     }
440
441     // Debugging
442
private String JavaDoc getNodeTypeFromCode(short code) {
443     String JavaDoc retval = null;
444     switch (code) {
445     case Node.ATTRIBUTE_NODE :
446         retval = "ATTRIBUTE_NODE"; break;
447     case Node.CDATA_SECTION_NODE :
448         retval = "CDATA_SECTION_NODE"; break;
449     case Node.COMMENT_NODE :
450         retval = "COMMENT_NODE"; break;
451     case Node.DOCUMENT_FRAGMENT_NODE :
452         retval = "DOCUMENT_FRAGMENT_NODE"; break;
453     case Node.DOCUMENT_NODE :
454         retval = "DOCUMENT_NODE"; break;
455     case Node.DOCUMENT_TYPE_NODE :
456         retval = "DOCUMENT_TYPE_NODE"; break;
457     case Node.ELEMENT_NODE :
458         retval = "ELEMENT_NODE"; break;
459     case Node.ENTITY_NODE :
460         retval = "ENTITY_NODE"; break;
461     case Node.ENTITY_REFERENCE_NODE :
462         retval = "ENTITY_REFERENCE_NODE"; break;
463     case Node.NOTATION_NODE :
464         retval = "NOTATION_NODE"; break;
465     case Node.PROCESSING_INSTRUCTION_NODE :
466         retval = "PROCESSING_INSTRUCTION_NODE"; break;
467     case Node.TEXT_NODE:
468         retval = "TEXT_NODE"; break;
469         }
470     return retval;
471     }
472 }
473
Popular Tags