KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > serializer > TreeWalker


1 /*
2  * Copyright 1999-2005 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: TreeWalker.java,v 1.1.4.1 2005/09/08 10:58:44 suresh_emailid Exp $
18  */

19 package com.sun.org.apache.xml.internal.serializer;
20
21 import java.io.File JavaDoc;
22
23 import com.sun.org.apache.xml.internal.serializer.utils.AttList;
24 import com.sun.org.apache.xml.internal.serializer.utils.DOM2Helper;
25 import org.w3c.dom.Comment JavaDoc;
26 import org.w3c.dom.Element JavaDoc;
27 import org.w3c.dom.EntityReference JavaDoc;
28 import org.w3c.dom.NamedNodeMap JavaDoc;
29 import org.w3c.dom.Node JavaDoc;
30 import org.w3c.dom.ProcessingInstruction JavaDoc;
31 import org.w3c.dom.Text JavaDoc;
32
33 import org.xml.sax.ContentHandler JavaDoc;
34 import org.xml.sax.Locator JavaDoc;
35 import org.xml.sax.ext.LexicalHandler JavaDoc;
36 import org.xml.sax.helpers.LocatorImpl JavaDoc;
37
38 /**
39  * This class does a pre-order walk of the DOM tree, calling a ContentHandler
40  * interface as it goes.
41  *
42  * This class is a copy of the one in com.sun.org.apache.xml.internal.utils.
43  * It exists to cut the serializers dependancy on that package.
44  *
45  * @xsl.usage internal
46  */

47
48 public final class TreeWalker
49 {
50
51   /** Local reference to a ContentHandler */
52   final private ContentHandler JavaDoc m_contentHandler;
53   /**
54    * If m_contentHandler is a SerializationHandler, then this is
55    * a reference to the same object.
56    */

57   final private SerializationHandler m_Serializer;
58
59   // ARGHH!! JAXP Uses Xerces without setting the namespace processing to ON!
60
// DOM2Helper m_dh = new DOM2Helper();
61

62   /** DomHelper for this TreeWalker */
63   final protected DOM2Helper m_dh;
64         
65   /** Locator object for this TreeWalker */
66   final private LocatorImpl JavaDoc m_locator = new LocatorImpl JavaDoc();
67
68   /**
69    * Get the ContentHandler used for the tree walk.
70    *
71    * @return the ContentHandler used for the tree walk
72    */

73   public ContentHandler JavaDoc getContentHandler()
74   {
75     return m_contentHandler;
76   }
77   
78   public TreeWalker(ContentHandler JavaDoc ch) {
79       this(ch,null);
80   }
81   /**
82    * Constructor.
83    * @param contentHandler The implemention of the
84    * contentHandler operation (toXMLString, digest, ...)
85    */

86   public TreeWalker(ContentHandler JavaDoc contentHandler, String JavaDoc systemId)
87   {
88       // Set the content handler
89
m_contentHandler = contentHandler;
90       if (m_contentHandler instanceof SerializationHandler) {
91           m_Serializer = (SerializationHandler) m_contentHandler;
92       }
93       else
94           m_Serializer = null;
95           
96       // Set the system ID, if it is given
97
m_contentHandler.setDocumentLocator(m_locator);
98       if (systemId != null)
99           m_locator.setSystemId(systemId);
100       else {
101           try {
102             // Bug see Bugzilla 26741
103
m_locator.setSystemId(System.getProperty("user.dir") + File.separator + "dummy.xsl");
104            }
105            catch (SecurityException JavaDoc se) {// user.dir not accessible from applet
106
}
107       }
108           
109       // Set the document locator
110
if (m_contentHandler != null)
111                         m_contentHandler.setDocumentLocator(m_locator);
112                 try {
113                    // Bug see Bugzilla 26741
114
m_locator.setSystemId(System.getProperty("user.dir") + File.separator + "dummy.xsl");
115                 }
116                 catch (SecurityException JavaDoc se){// user.dir not accessible from applet
117

118     }
119     m_dh = new DOM2Helper();
120   }
121
122   /**
123    * Perform a pre-order traversal non-recursive style.
124    *
125    * Note that TreeWalker assumes that the subtree is intended to represent
126    * a complete (though not necessarily well-formed) document and, during a
127    * traversal, startDocument and endDocument will always be issued to the
128    * SAX listener.
129    *
130    * @param pos Node in the tree where to start traversal
131    *
132    * @throws TransformerException
133    */

134   public void traverse(Node JavaDoc pos) throws org.xml.sax.SAXException JavaDoc
135   {
136
137     this.m_contentHandler.startDocument();
138
139     Node JavaDoc top = pos;
140
141     while (null != pos)
142     {
143       startNode(pos);
144
145       Node JavaDoc nextNode = pos.getFirstChild();
146
147       while (null == nextNode)
148       {
149         endNode(pos);
150
151         if (top.equals(pos))
152           break;
153
154         nextNode = pos.getNextSibling();
155
156         if (null == nextNode)
157         {
158           pos = pos.getParentNode();
159
160           if ((null == pos) || (top.equals(pos)))
161           {
162             if (null != pos)
163               endNode(pos);
164
165             nextNode = null;
166
167             break;
168           }
169         }
170       }
171
172       pos = nextNode;
173     }
174     this.m_contentHandler.endDocument();
175   }
176
177   /**
178    * Perform a pre-order traversal non-recursive style.
179
180    * Note that TreeWalker assumes that the subtree is intended to represent
181    * a complete (though not necessarily well-formed) document and, during a
182    * traversal, startDocument and endDocument will always be issued to the
183    * SAX listener.
184    *
185    * @param pos Node in the tree where to start traversal
186    * @param top Node in the tree where to end traversal
187    *
188    * @throws TransformerException
189    */

190   public void traverse(Node JavaDoc pos, Node JavaDoc top) throws org.xml.sax.SAXException JavaDoc
191   {
192
193     this.m_contentHandler.startDocument();
194     
195     while (null != pos)
196     {
197       startNode(pos);
198
199       Node JavaDoc nextNode = pos.getFirstChild();
200
201       while (null == nextNode)
202       {
203         endNode(pos);
204
205         if ((null != top) && top.equals(pos))
206           break;
207
208         nextNode = pos.getNextSibling();
209
210         if (null == nextNode)
211         {
212           pos = pos.getParentNode();
213
214           if ((null == pos) || ((null != top) && top.equals(pos)))
215           {
216             nextNode = null;
217
218             break;
219           }
220         }
221       }
222
223       pos = nextNode;
224     }
225     this.m_contentHandler.endDocument();
226   }
227
228   /** Flag indicating whether following text to be processed is raw text */
229   boolean nextIsRaw = false;
230   
231   /**
232    * Optimized dispatch of characters.
233    */

234   private final void dispatachChars(Node JavaDoc node)
235      throws org.xml.sax.SAXException JavaDoc
236   {
237     if(m_Serializer != null)
238     {
239       this.m_Serializer.characters(node);
240     }
241     else
242     {
243       String JavaDoc data = ((Text JavaDoc) node).getData();
244       this.m_contentHandler.characters(data.toCharArray(), 0, data.length());
245     }
246   }
247
248   /**
249    * Start processing given node
250    *
251    *
252    * @param node Node to process
253    *
254    * @throws org.xml.sax.SAXException
255    */

256   protected void startNode(Node JavaDoc node) throws org.xml.sax.SAXException JavaDoc
257   {
258
259 // TODO: <REVIEW>
260
// A Serializer implements ContentHandler, but not NodeConsumer
261
// so drop this reference to NodeConsumer which would otherwise
262
// pull in all sorts of things
263
// if (m_contentHandler instanceof NodeConsumer)
264
// {
265
// ((NodeConsumer) m_contentHandler).setOriginatingNode(node);
266
// }
267
// TODO: </REVIEW>
268

269                 if (node instanceof Locator JavaDoc)
270                 {
271                         Locator JavaDoc loc = (Locator JavaDoc)node;
272                         m_locator.setColumnNumber(loc.getColumnNumber());
273                         m_locator.setLineNumber(loc.getLineNumber());
274                         m_locator.setPublicId(loc.getPublicId());
275                         m_locator.setSystemId(loc.getSystemId());
276                 }
277                 else
278                 {
279                         m_locator.setColumnNumber(0);
280       m_locator.setLineNumber(0);
281                 }
282
283     switch (node.getNodeType())
284     {
285     case Node.COMMENT_NODE :
286     {
287       String JavaDoc data = ((Comment JavaDoc) node).getData();
288
289       if (m_contentHandler instanceof LexicalHandler JavaDoc)
290       {
291         LexicalHandler JavaDoc lh = ((LexicalHandler JavaDoc) this.m_contentHandler);
292
293         lh.comment(data.toCharArray(), 0, data.length());
294       }
295     }
296     break;
297     case Node.DOCUMENT_FRAGMENT_NODE :
298
299       // ??;
300
break;
301     case Node.DOCUMENT_NODE :
302     
303       break;
304     case Node.ELEMENT_NODE :
305       Element JavaDoc elem_node = (Element JavaDoc) node;
306       {
307           // Make sure the namespace node
308
// for the element itself is declared
309
// to the ContentHandler
310
String JavaDoc uri = elem_node.getNamespaceURI();
311           if (uri != null) {
312               String JavaDoc prefix = elem_node.getPrefix();
313               if (prefix==null)
314                 prefix="";
315               this.m_contentHandler.startPrefixMapping(prefix,uri);
316           }
317       }
318       NamedNodeMap JavaDoc atts = elem_node.getAttributes();
319       int nAttrs = atts.getLength();
320       // System.out.println("TreeWalker#startNode: "+node.getNodeName());
321

322       
323       // Make sure the namespace node of
324
// each attribute is declared to the ContentHandler
325
for (int i = 0; i < nAttrs; i++)
326       {
327         final Node JavaDoc attr = atts.item(i);
328         final String JavaDoc attrName = attr.getNodeName();
329         final int colon = attrName.indexOf(':');
330         final String JavaDoc prefix;
331
332         // System.out.println("TreeWalker#startNode: attr["+i+"] = "+attrName+", "+attr.getNodeValue());
333
if (attrName.equals("xmlns") || attrName.startsWith("xmlns:"))
334         {
335           // Use "" instead of null, as Xerces likes "" for the
336
// name of the default namespace. Fix attributed
337
// to "Steven Murray" <smurray@ebt.com>.
338
if (colon < 0)
339             prefix = "";
340           else
341             prefix = attrName.substring(colon + 1);
342
343           this.m_contentHandler.startPrefixMapping(prefix,
344                                                    attr.getNodeValue());
345         }
346         else if (colon > 0) {
347             prefix = attrName.substring(0,colon);
348             String JavaDoc uri = attr.getNamespaceURI();
349             if (uri != null)
350                 this.m_contentHandler.startPrefixMapping(prefix,uri);
351         }
352       }
353
354       String JavaDoc ns = m_dh.getNamespaceOfNode(node);
355       if(null == ns)
356         ns = "";
357       this.m_contentHandler.startElement(ns,
358                                          m_dh.getLocalNameOfNode(node),
359                                          node.getNodeName(),
360                                          new AttList(atts, m_dh));
361       break;
362     case Node.PROCESSING_INSTRUCTION_NODE :
363     {
364       ProcessingInstruction JavaDoc pi = (ProcessingInstruction JavaDoc) node;
365       String JavaDoc name = pi.getNodeName();
366
367       // String data = pi.getData();
368
if (name.equals("xslt-next-is-raw"))
369       {
370         nextIsRaw = true;
371       }
372       else
373       {
374         this.m_contentHandler.processingInstruction(pi.getNodeName(),
375                                                     pi.getData());
376       }
377     }
378     break;
379     case Node.CDATA_SECTION_NODE :
380     {
381       boolean isLexH = (m_contentHandler instanceof LexicalHandler JavaDoc);
382       LexicalHandler JavaDoc lh = isLexH
383                           ? ((LexicalHandler JavaDoc) this.m_contentHandler) : null;
384
385       if (isLexH)
386       {
387         lh.startCDATA();
388       }
389       
390       dispatachChars(node);
391
392       {
393         if (isLexH)
394         {
395           lh.endCDATA();
396         }
397       }
398     }
399     break;
400     case Node.TEXT_NODE :
401     {
402       //String data = ((Text) node).getData();
403

404       if (nextIsRaw)
405       {
406         nextIsRaw = false;
407
408         m_contentHandler.processingInstruction(javax.xml.transform.Result.PI_DISABLE_OUTPUT_ESCAPING, "");
409         dispatachChars(node);
410         m_contentHandler.processingInstruction(javax.xml.transform.Result.PI_ENABLE_OUTPUT_ESCAPING, "");
411       }
412       else
413       {
414         dispatachChars(node);
415       }
416     }
417     break;
418     case Node.ENTITY_REFERENCE_NODE :
419     {
420       EntityReference JavaDoc eref = (EntityReference JavaDoc) node;
421
422       if (m_contentHandler instanceof LexicalHandler JavaDoc)
423       {
424         ((LexicalHandler JavaDoc) this.m_contentHandler).startEntity(
425           eref.getNodeName());
426       }
427       else
428       {
429
430         // warning("Can not output entity to a pure SAX ContentHandler");
431
}
432     }
433     break;
434     default :
435     }
436   }
437
438   /**
439    * End processing of given node
440    *
441    *
442    * @param node Node we just finished processing
443    *
444    * @throws org.xml.sax.SAXException
445    */

446   protected void endNode(Node JavaDoc node) throws org.xml.sax.SAXException JavaDoc
447   {
448
449     switch (node.getNodeType())
450     {
451     case Node.DOCUMENT_NODE :
452       break;
453       
454     case Node.ELEMENT_NODE :
455       String JavaDoc ns = m_dh.getNamespaceOfNode(node);
456       if(null == ns)
457         ns = "";
458       this.m_contentHandler.endElement(ns,
459                                          m_dh.getLocalNameOfNode(node),
460                                          node.getNodeName());
461
462       if (m_Serializer == null) {
463       // Don't bother with endPrefixMapping calls if the ContentHandler is a
464
// SerializationHandler because SerializationHandler's ignore the
465
// endPrefixMapping() calls anyways. . . . This is an optimization.
466
Element JavaDoc elem_node = (Element JavaDoc) node;
467       NamedNodeMap JavaDoc atts = elem_node.getAttributes();
468       int nAttrs = atts.getLength();
469
470       // do the endPrefixMapping calls in reverse order
471
// of the startPrefixMapping calls
472
for (int i = (nAttrs-1); 0 <= i; i--)
473       {
474         final Node JavaDoc attr = atts.item(i);
475         final String JavaDoc attrName = attr.getNodeName();
476         final int colon = attrName.indexOf(':');
477         final String JavaDoc prefix;
478
479         if (attrName.equals("xmlns") || attrName.startsWith("xmlns:"))
480         {
481           // Use "" instead of null, as Xerces likes "" for the
482
// name of the default namespace. Fix attributed
483
// to "Steven Murray" <smurray@ebt.com>.
484
if (colon < 0)
485             prefix = "";
486           else
487             prefix = attrName.substring(colon + 1);
488
489           this.m_contentHandler.endPrefixMapping(prefix);
490         }
491         else if (colon > 0) {
492             prefix = attrName.substring(0, colon);
493             this.m_contentHandler.endPrefixMapping(prefix);
494         }
495       }
496       {
497           String JavaDoc uri = elem_node.getNamespaceURI();
498           if (uri != null) {
499               String JavaDoc prefix = elem_node.getPrefix();
500               if (prefix==null)
501                 prefix="";
502               this.m_contentHandler.endPrefixMapping(prefix);
503           }
504       }
505       }
506       break;
507     case Node.CDATA_SECTION_NODE :
508       break;
509     case Node.ENTITY_REFERENCE_NODE :
510     {
511       EntityReference JavaDoc eref = (EntityReference JavaDoc) node;
512
513       if (m_contentHandler instanceof LexicalHandler JavaDoc)
514       {
515         LexicalHandler JavaDoc lh = ((LexicalHandler JavaDoc) this.m_contentHandler);
516
517         lh.endEntity(eref.getNodeName());
518       }
519     }
520     break;
521     default :
522     }
523   }
524 } //TreeWalker
525

526
Popular Tags