KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > utils > TreeWalker


1 /*
2  * Copyright 1999-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: TreeWalker.java,v 1.22 2004/02/17 04:21:14 minchau Exp $
18  */

19 package org.apache.xml.utils;
20
21 import java.io.File JavaDoc;
22
23 import org.w3c.dom.Comment JavaDoc;
24 import org.w3c.dom.Element JavaDoc;
25 import org.w3c.dom.EntityReference JavaDoc;
26 import org.w3c.dom.NamedNodeMap JavaDoc;
27 import org.w3c.dom.Node JavaDoc;
28 import org.w3c.dom.ProcessingInstruction JavaDoc;
29 import org.w3c.dom.Text JavaDoc;
30
31 import org.xml.sax.ContentHandler JavaDoc;
32 import org.xml.sax.Locator JavaDoc;
33 import org.xml.sax.ext.LexicalHandler JavaDoc;
34 import org.xml.sax.helpers.LocatorImpl JavaDoc;
35
36 /**
37  * This class does a pre-order walk of the DOM tree, calling a ContentHandler
38  * interface as it goes.
39  * @xsl.usage advanced
40  */

41
42 public class TreeWalker
43 {
44
45   /** Local reference to a ContentHandler */
46   private ContentHandler JavaDoc m_contentHandler = null;
47
48   // ARGHH!! JAXP Uses Xerces without setting the namespace processing to ON!
49
// DOM2Helper m_dh = new DOM2Helper();
50

51   /** DomHelper for this TreeWalker */
52   protected DOMHelper m_dh;
53         
54         /** Locator object for this TreeWalker */
55         private LocatorImpl JavaDoc m_locator = new LocatorImpl JavaDoc();
56
57   /**
58    * Get the ContentHandler used for the tree walk.
59    *
60    * @return the ContentHandler used for the tree walk
61    */

62   public ContentHandler JavaDoc getContentHandler()
63   {
64     return m_contentHandler;
65   }
66
67   /**
68    * Get the ContentHandler used for the tree walk.
69    *
70    * @return the ContentHandler used for the tree walk
71    */

72   public void setContentHandler(ContentHandler JavaDoc ch)
73   {
74     m_contentHandler = ch;
75   }
76         
77         /**
78    * Constructor.
79    * @param contentHandler The implemention of the
80    * @param systemId System identifier for the document.
81    * contentHandler operation (toXMLString, digest, ...)
82    */

83   public TreeWalker(ContentHandler JavaDoc contentHandler, DOMHelper dh, String JavaDoc systemId)
84   {
85     this.m_contentHandler = contentHandler;
86     m_contentHandler.setDocumentLocator(m_locator);
87     if (systemId != null)
88         m_locator.setSystemId(systemId);
89     else {
90         try {
91           // Bug see Bugzilla 26741
92
m_locator.setSystemId(System.getProperty("user.dir") + File.separator + "dummy.xsl");
93          }
94          catch (SecurityException JavaDoc se) {// user.dir not accessible from applet
95
}
96     }
97     m_dh = dh;
98   }
99
100   /**
101    * Constructor.
102    * @param contentHandler The implemention of the
103    * contentHandler operation (toXMLString, digest, ...)
104    */

105   public TreeWalker(ContentHandler JavaDoc contentHandler, DOMHelper dh)
106   {
107     this.m_contentHandler = contentHandler;
108     m_contentHandler.setDocumentLocator(m_locator);
109     try {
110        // Bug see Bugzilla 26741
111
m_locator.setSystemId(System.getProperty("user.dir") + File.separator + "dummy.xsl");
112     }
113     catch (SecurityException JavaDoc se){// user.dir not accessible from applet
114
}
115     m_dh = dh;
116   }
117   
118   /**
119    * Constructor.
120    * @param contentHandler The implemention of the
121    * contentHandler operation (toXMLString, digest, ...)
122    */

123   public TreeWalker(ContentHandler JavaDoc contentHandler)
124   {
125     this.m_contentHandler = contentHandler;
126                 if (m_contentHandler != null)
127                         m_contentHandler.setDocumentLocator(m_locator);
128                 try {
129                    // Bug see Bugzilla 26741
130
m_locator.setSystemId(System.getProperty("user.dir") + File.separator + "dummy.xsl");
131                 }
132                 catch (SecurityException JavaDoc se){// user.dir not accessible from applet
133

134     }
135     m_dh = new DOM2Helper();
136   }
137
138   /**
139    * Perform a pre-order traversal non-recursive style.
140    *
141    * Note that TreeWalker assumes that the subtree is intended to represent
142    * a complete (though not necessarily well-formed) document and, during a
143    * traversal, startDocument and endDocument will always be issued to the
144    * SAX listener.
145    *
146    * @param pos Node in the tree where to start traversal
147    *
148    * @throws TransformerException
149    */

150   public void traverse(Node JavaDoc pos) throws org.xml.sax.SAXException JavaDoc
151   {
152
153     this.m_contentHandler.startDocument();
154
155     Node JavaDoc top = pos;
156
157     while (null != pos)
158     {
159       startNode(pos);
160
161       Node JavaDoc nextNode = pos.getFirstChild();
162
163       while (null == nextNode)
164       {
165         endNode(pos);
166
167         if (top.equals(pos))
168           break;
169
170         nextNode = pos.getNextSibling();
171
172         if (null == nextNode)
173         {
174           pos = pos.getParentNode();
175
176           if ((null == pos) || (top.equals(pos)))
177           {
178             if (null != pos)
179               endNode(pos);
180
181             nextNode = null;
182
183             break;
184           }
185         }
186       }
187
188       pos = nextNode;
189     }
190     this.m_contentHandler.endDocument();
191   }
192
193   /**
194    * Perform a pre-order traversal non-recursive style.
195
196    * Note that TreeWalker assumes that the subtree is intended to represent
197    * a complete (though not necessarily well-formed) document and, during a
198    * traversal, startDocument and endDocument will always be issued to the
199    * SAX listener.
200    *
201    * @param pos Node in the tree where to start traversal
202    * @param top Node in the tree where to end traversal
203    *
204    * @throws TransformerException
205    */

206   public void traverse(Node JavaDoc pos, Node JavaDoc top) throws org.xml.sax.SAXException JavaDoc
207   {
208
209     this.m_contentHandler.startDocument();
210     
211     while (null != pos)
212     {
213       startNode(pos);
214
215       Node JavaDoc nextNode = pos.getFirstChild();
216
217       while (null == nextNode)
218       {
219         endNode(pos);
220
221         if ((null != top) && top.equals(pos))
222           break;
223
224         nextNode = pos.getNextSibling();
225
226         if (null == nextNode)
227         {
228           pos = pos.getParentNode();
229
230           if ((null == pos) || ((null != top) && top.equals(pos)))
231           {
232             nextNode = null;
233
234             break;
235           }
236         }
237       }
238
239       pos = nextNode;
240     }
241     this.m_contentHandler.endDocument();
242   }
243
244   /** Flag indicating whether following text to be processed is raw text */
245   boolean nextIsRaw = false;
246   
247   /**
248    * Optimized dispatch of characters.
249    */

250   private final void dispatachChars(Node JavaDoc node)
251      throws org.xml.sax.SAXException JavaDoc
252   {
253     if(m_contentHandler instanceof org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.CharacterNodeHandler)
254     {
255       ((org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.CharacterNodeHandler)m_contentHandler).characters(node);
256     }
257     else
258     {
259       String JavaDoc data = ((Text JavaDoc) node).getData();
260       this.m_contentHandler.characters(data.toCharArray(), 0, data.length());
261     }
262   }
263
264   /**
265    * Start processing given node
266    *
267    *
268    * @param node Node to process
269    *
270    * @throws org.xml.sax.SAXException
271    */

272   protected void startNode(Node JavaDoc node) throws org.xml.sax.SAXException JavaDoc
273   {
274
275     if (m_contentHandler instanceof NodeConsumer)
276     {
277       ((NodeConsumer) m_contentHandler).setOriginatingNode(node);
278     }
279                 
280                 if (node instanceof Locator JavaDoc)
281                 {
282                         Locator JavaDoc loc = (Locator JavaDoc)node;
283                         m_locator.setColumnNumber(loc.getColumnNumber());
284                         m_locator.setLineNumber(loc.getLineNumber());
285                         m_locator.setPublicId(loc.getPublicId());
286                         m_locator.setSystemId(loc.getSystemId());
287                 }
288                 else
289                 {
290                         m_locator.setColumnNumber(0);
291       m_locator.setLineNumber(0);
292                 }
293
294     switch (node.getNodeType())
295     {
296     case Node.COMMENT_NODE :
297     {
298       String JavaDoc data = ((Comment JavaDoc) node).getData();
299
300       if (m_contentHandler instanceof LexicalHandler JavaDoc)
301       {
302         LexicalHandler JavaDoc lh = ((LexicalHandler JavaDoc) this.m_contentHandler);
303
304         lh.comment(data.toCharArray(), 0, data.length());
305       }
306     }
307     break;
308     case Node.DOCUMENT_FRAGMENT_NODE :
309
310       // ??;
311
break;
312     case Node.DOCUMENT_NODE :
313     
314       break;
315     case Node.ELEMENT_NODE :
316       NamedNodeMap JavaDoc atts = ((Element JavaDoc) node).getAttributes();
317       int nAttrs = atts.getLength();
318       // System.out.println("TreeWalker#startNode: "+node.getNodeName());
319

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

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

436   protected void endNode(Node JavaDoc node) throws org.xml.sax.SAXException JavaDoc
437   {
438
439     switch (node.getNodeType())
440     {
441     case Node.DOCUMENT_NODE :
442       break;
443       
444     case Node.ELEMENT_NODE :
445       String JavaDoc ns = m_dh.getNamespaceOfNode(node);
446       if(null == ns)
447         ns = "";
448       this.m_contentHandler.endElement(ns,
449                                          m_dh.getLocalNameOfNode(node),
450                                          node.getNodeName());
451
452       NamedNodeMap JavaDoc atts = ((Element JavaDoc) node).getAttributes();
453       int nAttrs = atts.getLength();
454
455       for (int i = 0; i < nAttrs; i++)
456       {
457         Node JavaDoc attr = atts.item(i);
458         String JavaDoc attrName = attr.getNodeName();
459
460         if (attrName.equals("xmlns") || attrName.startsWith("xmlns:"))
461         {
462           int index;
463           // Use "" instead of null, as Xerces likes "" for the
464
// name of the default namespace. Fix attributed
465
// to "Steven Murray" <smurray@ebt.com>.
466
String JavaDoc prefix = (index = attrName.indexOf(":")) < 0
467                           ? "" : attrName.substring(index + 1);
468
469           this.m_contentHandler.endPrefixMapping(prefix);
470         }
471       }
472       break;
473     case Node.CDATA_SECTION_NODE :
474       break;
475     case Node.ENTITY_REFERENCE_NODE :
476     {
477       EntityReference JavaDoc eref = (EntityReference JavaDoc) node;
478
479       if (m_contentHandler instanceof LexicalHandler JavaDoc)
480       {
481         LexicalHandler JavaDoc lh = ((LexicalHandler JavaDoc) this.m_contentHandler);
482
483         lh.endEntity(eref.getNodeName());
484       }
485     }
486     break;
487     default :
488     }
489   }
490 } //TreeWalker
491

492
Popular Tags