KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > xml > dom > DOMStreamer


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 package org.apache.cocoon.xml.dom;
17
18 import java.util.HashMap JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import javax.xml.transform.Transformer JavaDoc;
23 import javax.xml.transform.TransformerConfigurationException JavaDoc;
24 import javax.xml.transform.TransformerException JavaDoc;
25 import javax.xml.transform.TransformerFactory JavaDoc;
26 import javax.xml.transform.dom.DOMSource JavaDoc;
27 import javax.xml.transform.sax.SAXResult JavaDoc;
28
29 import org.apache.cocoon.xml.AbstractXMLProducer;
30 import org.apache.cocoon.xml.EmbeddedXMLPipe;
31 import org.apache.cocoon.xml.XMLConsumer;
32 import org.apache.cocoon.xml.XMLProducer;
33 import org.apache.commons.lang.StringUtils;
34
35 import org.w3c.dom.Attr JavaDoc;
36 import org.w3c.dom.Comment JavaDoc;
37 import org.w3c.dom.Element JavaDoc;
38 import org.w3c.dom.EntityReference JavaDoc;
39 import org.w3c.dom.NamedNodeMap JavaDoc;
40 import org.w3c.dom.Node JavaDoc;
41 import org.w3c.dom.ProcessingInstruction JavaDoc;
42 import org.w3c.dom.Text JavaDoc;
43 import org.xml.sax.ContentHandler JavaDoc;
44 import org.xml.sax.SAXException JavaDoc;
45 import org.xml.sax.ext.LexicalHandler JavaDoc;
46 import org.xml.sax.helpers.AttributesImpl JavaDoc;
47
48 /**
49  * The <code>DOMStreamer</code> is a utility class that will generate SAX
50  * events from a W3C DOM Document.
51  *
52  * <p>The DOMStreamer uses a different strategy based on the value of the
53  * normalizeNamespaces property:
54  * <ul>
55  * <li>if true (the default), the DOMStreamer will normalize namespace
56  * declarations (i.e. add missing xmlns attributes or correct them). See
57  * also {@link NamespaceNormalizingDOMStreamer}.
58  * <li>if false, the standard JAXP identity transformer is used.
59  * </ul>
60  *
61  * @author <a HREF="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
62  * @author <a HREF="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
63  * (Apache Software Foundation)
64  * @version CVS $Id: DOMStreamer.java 151345 2005-02-04 12:41:52Z michi $
65  */

66 public class DOMStreamer implements XMLProducer {
67
68     /** Default value for normalizeNamespaces. */
69     private final static boolean DEFAULT_NORMALIZE_NAMESPACES = true;
70
71     /** Indicates whether namespace normalization should happen. */
72     protected boolean normalizeNamespaces = DEFAULT_NORMALIZE_NAMESPACES;
73
74     /** DOMStreamer used in case of namespace normalization. */
75     protected NamespaceNormalizingDOMStreamer namespaceNormalizingDOMStreamer = new NamespaceNormalizingDOMStreamer();
76
77     /** DOMStreamer used when namespace normalization should not explicitely happen. */
78     protected DefaultDOMStreamer defaultDOMStreamer = new DefaultDOMStreamer();
79
80     /** The transformer factory shared by all instances (only used by DefaultDOMStreamer) */
81     protected final static TransformerFactory JavaDoc factory = TransformerFactory.newInstance();
82
83     /**
84      * Create a new <code>DOMStreamer</code> instance.
85      */

86     public DOMStreamer() {
87         super();
88     }
89
90     /**
91      * Create a new <code>DOMStreamer</code> instance.
92      */

93     public DOMStreamer(XMLConsumer consumer) {
94         this(consumer, consumer);
95     }
96
97     /**
98      * Create a new <code>DOMStreamer</code> instance.
99      */

100     public DOMStreamer(ContentHandler JavaDoc content) {
101         this(content, null);
102         if (content instanceof LexicalHandler JavaDoc) {
103             defaultDOMStreamer.setLexicalHandler((LexicalHandler JavaDoc) content);
104             namespaceNormalizingDOMStreamer.setLexicalHandler((LexicalHandler JavaDoc) content);
105         }
106     }
107
108     /**
109      * Create a new <code>DOMStreamer</code> instance.
110      */

111     public DOMStreamer(ContentHandler JavaDoc content, LexicalHandler JavaDoc lexical) {
112         this();
113         defaultDOMStreamer.setContentHandler(content);
114         defaultDOMStreamer.setLexicalHandler(lexical);
115         namespaceNormalizingDOMStreamer.setContentHandler(content);
116         namespaceNormalizingDOMStreamer.setLexicalHandler(lexical);
117     }
118
119     /**
120      * Set the <code>XMLConsumer</code> that will receive XML data.
121      */

122     public void setConsumer(XMLConsumer consumer) {
123         defaultDOMStreamer.setContentHandler(consumer);
124         defaultDOMStreamer.setLexicalHandler(consumer);
125         namespaceNormalizingDOMStreamer.setContentHandler(consumer);
126         namespaceNormalizingDOMStreamer.setLexicalHandler(consumer);
127     }
128
129     /**
130      * Set the <code>ContentHandler</code> that will receive XML data.
131      */

132     public void setContentHandler(ContentHandler JavaDoc handler) {
133         defaultDOMStreamer.setContentHandler(handler);
134         namespaceNormalizingDOMStreamer.setContentHandler(handler);
135     }
136
137     /**
138      * Set the <code>LexicalHandler</code> that will receive XML data.
139      */

140     public void setLexicalHandler(LexicalHandler JavaDoc handler) {
141         defaultDOMStreamer.setLexicalHandler(handler);
142         namespaceNormalizingDOMStreamer.setLexicalHandler(handler);
143     }
144
145     /**
146      * Start the production of SAX events.
147      */

148     public void stream(Node JavaDoc node) throws SAXException JavaDoc {
149         if (normalizeNamespaces) {
150             namespaceNormalizingDOMStreamer.stream(node);
151         } else {
152             defaultDOMStreamer.stream(node);
153         }
154     }
155
156     public boolean isNormalizeNamespaces() {
157         return normalizeNamespaces;
158     }
159
160     public void setNormalizeNamespaces(boolean normalizeNamespaces) {
161         this.normalizeNamespaces = normalizeNamespaces;
162     }
163
164     public void recycle() {
165         defaultDOMStreamer.recycle();
166         namespaceNormalizingDOMStreamer.recycle();
167         normalizeNamespaces = DEFAULT_NORMALIZE_NAMESPACES;
168     }
169
170     /**
171      * Streams a DOM tree to SAX events and normalizes namespace declarations on the way.
172      *
173      * <p>The code in this class is based on the org.apache.xml.utils.TreeWalker class from Xalan,
174      * though it differs in some important ways.
175      *
176      * <p>This class will automatically fix up ("normalize") namespace declarations
177      * while streaming to SAX. The original DOM-tree is not modified. The algorithm
178      * used is described in
179      * <a HREF="http://www.w3.org/TR/2002/WD-DOM-Level-3-Core-20021022/namespaces-algorithms.html#normalizeDocumentAlgo">an appendix of the DOM Level 3 spec</a>.
180      *
181      * <p>This class will NOT check the correctness of namespaces, e.g. it will not
182      * check that the "xml" prefix is not misused etc.
183      *
184      * @author Bruno Dumon (bruno at outerthought dot org)
185      * @author Xalan team
186      */

187     public static class NamespaceNormalizingDOMStreamer extends AbstractXMLProducer {
188         /**
189          * Information about the current element. Used to remember the localName, qName
190          * and namespaceURI for generating the endElement event, and holds the namespaces
191          * declared on the element. This extra class is needed because we don't want to
192          * modify the DOM-tree itself. The currentElementInfo has a pointer to its parent
193          * elementInfo.
194          */

195         protected NamespaceNormalizingDOMStreamer.ElementInfo currentElementInfo = null;
196
197         /** Counter used when generating new namespace prefixes. */
198         protected int newPrefixCounter = 0;
199
200         public void recycle() {
201             super.recycle();
202             currentElementInfo = null;
203             newPrefixCounter = 0;
204         }
205
206         /**
207          * Start the production of SAX events.
208          *
209          * <p>Perform a pre-order traversal non-recursive style.
210          *
211          * <p>Note that TreeWalker assumes that the subtree is intended to represent
212          * a complete (though not necessarily well-formed) document and, during a
213          * traversal, startDocument and endDocument will always be issued to the
214          * SAX listener.
215          *
216          * @param pos Node in the tree where to start traversal
217          *
218          */

219         protected void stream(Node JavaDoc pos) throws SAXException JavaDoc {
220
221             // Start document only if we're streaming a document
222
boolean isDoc = (pos.getNodeType() == Node.DOCUMENT_NODE);
223             if (isDoc) {
224               contentHandler.startDocument();
225             }
226
227             Node JavaDoc top = pos;
228             while (null != pos) {
229                 startNode(pos);
230
231                 Node JavaDoc nextNode = pos.getFirstChild();
232                 while (null == nextNode) {
233                     endNode(pos);
234
235                     if (top.equals(pos)) {
236                         break;
237                     }
238
239                     nextNode = pos.getNextSibling();
240                     if (null == nextNode) {
241                         pos = pos.getParentNode();
242
243                         if ((null == pos) || (top.equals(pos))) {
244                             if (null != pos) {
245                                 endNode(pos);
246                             }
247                             nextNode = null;
248
249                             break;
250                         }
251                     }
252                 }
253
254                 pos = nextNode;
255             }
256
257             if (isDoc) {
258                 contentHandler.endDocument();
259             }
260         }
261
262         private final void dispatchChars(Node JavaDoc node) throws SAXException JavaDoc {
263             String JavaDoc data = ((Text JavaDoc) node).getData();
264             contentHandler.characters(data.toCharArray(), 0, data.length());
265         }
266
267         /**
268          * Start processing given node
269          *
270          * @param node Node to process
271          */

272         protected void startNode(Node JavaDoc node) throws SAXException JavaDoc {
273
274             switch (node.getNodeType()) {
275                 case Node.COMMENT_NODE:
276                     {
277                         if (lexicalHandler != null) {
278                             String JavaDoc data = ((Comment JavaDoc) node).getData();
279                             lexicalHandler.comment(data.toCharArray(), 0, data.length());
280                         }
281                     }
282                     break;
283                 case Node.DOCUMENT_FRAGMENT_NODE:
284
285                     // ??;
286
break;
287                 case Node.DOCUMENT_NODE:
288
289                     break;
290                 case Node.ELEMENT_NODE:
291                     NamedNodeMap JavaDoc atts = node.getAttributes();
292                     int nAttrs = atts.getLength();
293
294                     // create a list of localy declared namespace prefixes
295
currentElementInfo = new NamespaceNormalizingDOMStreamer.ElementInfo(currentElementInfo);
296                     for (int i = 0; i < nAttrs; i++) {
297                         Node JavaDoc attr = atts.item(i);
298                         String JavaDoc attrName = attr.getNodeName();
299
300                         if (attrName.equals("xmlns") || attrName.startsWith("xmlns:")) {
301                             int index;
302                             String JavaDoc prefix = (index = attrName.indexOf(":")) < 0
303                                     ? "" : attrName.substring(index + 1);
304
305                             currentElementInfo.put(prefix, attr.getNodeValue());
306                         }
307                     }
308
309                     String JavaDoc namespaceURI = node.getNamespaceURI();
310                     String JavaDoc prefix = node.getPrefix();
311                     String JavaDoc localName = node.getLocalName();
312
313                     if (localName == null) {
314                         // this is an element created with createElement instead of createElementNS
315
String JavaDoc[] prefixAndLocalName = getPrefixAndLocalName(node.getNodeName());
316                         prefix = prefixAndLocalName[0];
317                         localName = prefixAndLocalName[1];
318                         // note: if prefix is null, there can still be a default namespace...
319
namespaceURI = getNamespaceForPrefix(prefix, (Element JavaDoc)node);
320                     }
321
322                     if (namespaceURI != null) {
323                         // no prefix means: make this the default namespace
324
if (prefix == null) {
325                             prefix = "";
326                         }
327                         // check that is declared
328
String JavaDoc uri = currentElementInfo.findNamespaceURI(prefix);
329                         if (StringUtils.equals(uri, namespaceURI)) {
330                             // System.out.println("namespace is declared");
331
// prefix is declared correctly, do nothing
332
} else if (uri != null) {
333                             // System.out.println("prefix is declared with other namespace, overwriting it");
334
// prefix exists but is bound to another namespace, overwrite it
335
currentElementInfo.put(prefix, namespaceURI);
336                         } else {
337                             // System.out.println("prefix is not yet declared, declaring it now");
338
currentElementInfo.put(prefix, namespaceURI);
339                         }
340                     } else {
341                         // element has no namespace
342
// check if there is a default namespace, if so undeclare it
343
String JavaDoc uri = currentElementInfo.findNamespaceURI("");
344                         if (StringUtils.isNotEmpty(uri)) {
345                             // System.out.println("undeclaring default namespace");
346
currentElementInfo.put("", "");
347                         }
348                     }
349
350                     // SAX uses empty string to denote no namespace, while DOM uses null.
351
if (namespaceURI == null)
352                         namespaceURI = "";
353
354                     String JavaDoc qName;
355                     if (StringUtils.isNotEmpty(prefix)) {
356                         qName = prefix + ":" + localName;
357                     } else {
358                         qName = localName;
359                     }
360
361                     // make the attributes
362
AttributesImpl JavaDoc newAttrs = new AttributesImpl JavaDoc();
363                     for (int i = 0; i < nAttrs; i++) {
364                         Node JavaDoc attr = atts.item(i);
365                         String JavaDoc attrName = attr.getNodeName();
366                         String JavaDoc assignedAttrPrefix = null;
367
368                         // only do non-namespace attributes
369
if (!(attrName.equals("xmlns") || attrName.startsWith("xmlns:"))) {
370                             String JavaDoc attrPrefix;
371                             String JavaDoc attrLocalName;
372                             String JavaDoc attrNsURI;
373
374                             if (attr.getLocalName() == null) {
375                                 // this is an attribute created with setAttribute instead of setAttributeNS
376
String JavaDoc[] prefixAndLocalName = getPrefixAndLocalName(attrName);
377                                 attrPrefix = prefixAndLocalName[0];
378                                 // the statement below causes the attribute to keep its prefix even if it is not
379
// bound to a namespace (to support pre-namespace XML).
380
assignedAttrPrefix = attrPrefix;
381                                 attrLocalName = prefixAndLocalName[1];
382                                 // note: if prefix is null, the attribute has no namespace (namespace defaulting
383
// does not apply to attributes)
384
if (attrPrefix != null)
385                                     attrNsURI = getNamespaceForPrefix(attrPrefix, (Element JavaDoc)node);
386                                 else
387                                     attrNsURI = null;
388                             } else {
389                                 attrLocalName = attr.getLocalName();
390                                 attrPrefix = attr.getPrefix();
391                                 attrNsURI = attr.getNamespaceURI();
392                             }
393
394                             if (attrNsURI != null) {
395                                 String JavaDoc declaredUri = currentElementInfo.findNamespaceURI(attrPrefix);
396                                 // if the prefix is null, or the prefix has not been declared, or conflicts with an in-scope binding
397
if (declaredUri == null || !declaredUri.equals(attrNsURI)) {
398                                     String JavaDoc availablePrefix = currentElementInfo.findPrefix(attrNsURI);
399                                     if (availablePrefix != null && !availablePrefix.equals(""))
400                                         assignedAttrPrefix = availablePrefix;
401                                     else {
402                                         if (attrPrefix != null && declaredUri == null) {
403                                             // prefix is not null and is not yet declared: declare it
404
assignedAttrPrefix = attrPrefix;
405                                             currentElementInfo.put(assignedAttrPrefix, attrNsURI);
406                                         } else {
407                                             // attribute has no prefix (which is not allowed for namespaced attributes) or
408
// the prefix is already bound to something else: generate a new prefix
409
newPrefixCounter++;
410                                             assignedAttrPrefix = "NS" + newPrefixCounter;
411                                             currentElementInfo.put(assignedAttrPrefix, attrNsURI);
412                                         }
413                                     }
414                                 } else {
415                                     assignedAttrPrefix = attrPrefix;
416                                 }
417                             }
418
419                             String JavaDoc assignedAttrNsURI = attrNsURI != null ? attrNsURI : "";
420                             String JavaDoc attrQName;
421                             if (assignedAttrPrefix != null) {
422                                 attrQName = assignedAttrPrefix + ":" + attrLocalName;
423                             } else {
424                                 attrQName = attrLocalName;
425                             }
426                             newAttrs.addAttribute(assignedAttrNsURI, attrLocalName, attrQName, "CDATA", attr.getNodeValue());
427                         }
428                     }
429
430                     // add local namespace declaration and fire startPrefixMapping events
431
if (currentElementInfo.namespaceDeclarations != null && currentElementInfo.namespaceDeclarations.size() > 0) {
432                         Iterator JavaDoc localNsDeclIt = currentElementInfo.namespaceDeclarations.entrySet().iterator();
433                         while (localNsDeclIt.hasNext()) {
434                             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) localNsDeclIt.next();
435                             String JavaDoc pr = (String JavaDoc) entry.getKey();
436                             String JavaDoc ns = (String JavaDoc) entry.getValue();
437                             // the following lines enable the creation of explicit xmlns attributes
438
//String pr1 = pr.equals("") ? "xmlns" : pr;
439
//String qn = pr.equals("") ? "xmlns" : "xmlns:" + pr;
440
//newAttrs.addAttribute("", pr1, qn, "CDATA", ns);
441
// System.out.println("starting prefix mapping for prefix " + pr + " for " + ns);
442
contentHandler.startPrefixMapping(pr, ns);
443                         }
444                     }
445
446                     contentHandler.startElement(namespaceURI, localName, qName, newAttrs);
447
448                     currentElementInfo.localName = localName;
449                     currentElementInfo.namespaceURI = namespaceURI;
450                     currentElementInfo.qName = qName;
451                     break;
452                 case Node.PROCESSING_INSTRUCTION_NODE:
453                     {
454                         ProcessingInstruction JavaDoc pi = (ProcessingInstruction JavaDoc) node;
455                         contentHandler.processingInstruction(pi.getNodeName(), pi.getData());
456                     }
457                     break;
458                 case Node.CDATA_SECTION_NODE:
459                     {
460                         if (lexicalHandler != null)
461                             lexicalHandler.startCDATA();
462
463                         dispatchChars(node);
464
465                         if (lexicalHandler != null)
466                             lexicalHandler.endCDATA();
467                     }
468                     break;
469                 case Node.TEXT_NODE:
470                     {
471                         dispatchChars(node);
472                     }
473                     break;
474                 case Node.ENTITY_REFERENCE_NODE:
475                     {
476                         EntityReference JavaDoc eref = (EntityReference JavaDoc) node;
477
478                         if (lexicalHandler != null) {
479                             lexicalHandler.startEntity(eref.getNodeName());
480                         } else {
481                             // warning("Can not output entity to a pure SAX ContentHandler");
482
}
483                     }
484                     break;
485                 default :
486             }
487         }
488
489         /**
490          * Searches the namespace for a given namespace prefix starting from a
491          * given Element.
492          *
493          * <p>Note that this resolves the prefix in the orginal DOM-tree, not in
494          * the {@link ElementInfo} objects. This is used to resolve prefixes
495          * of elements or attributes created with createElement or setAttribute
496          * instead of createElementNS or setAttributeNS.
497          *
498          * <p>The code in this method is largely based on
499          * org.apache.xml.utils.DOMHelper.getNamespaceForPrefix() (from Xalan).
500          *
501          * @param prefix the prefix to look for, can be empty or null to find the
502          * default namespace
503          *
504          * @return the namespace, or null if not found.
505          */

506         public String JavaDoc getNamespaceForPrefix(String JavaDoc prefix, Element JavaDoc namespaceContext) {
507             int type;
508             Node JavaDoc parent = namespaceContext;
509             String JavaDoc namespace = null;
510
511             if (prefix == null)
512                 prefix = "";
513
514             if (prefix.equals("xml")) {
515                 namespace = "http://www.w3.org/XML/1998/namespace";
516             } else if(prefix.equals("xmlns")) {
517                 namespace = "http://www.w3.org/2000/xmlns/";
518             } else {
519                 // Attribute name for this prefix's declaration
520
String JavaDoc declname = (prefix == "") ? "xmlns" : "xmlns:" + prefix;
521
522                 // Scan until we run out of Elements or have resolved the namespace
523
while ((null != parent) && (null == namespace)
524                    && (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
525                        || (type == Node.ENTITY_REFERENCE_NODE))) {
526                     if (type == Node.ELEMENT_NODE) {
527                         Attr JavaDoc attr=((Element JavaDoc)parent).getAttributeNode(declname);
528                         if (attr != null) {
529                             namespace = attr.getNodeValue();
530                             break;
531                         }
532                     }
533                     parent = parent.getParentNode();
534                 }
535             }
536             return namespace;
537         }
538
539         /**
540          * Splits a nodeName into a prefix and a localName
541          *
542          * @return an array containing two elements, the first one is the prefix (can be null), the
543          * second one is the localName
544          */

545         private String JavaDoc[] getPrefixAndLocalName(String JavaDoc nodeName) {
546             String JavaDoc prefix, localName;
547             int colonPos = nodeName.indexOf(":");
548             if (colonPos != -1) {
549                 prefix = nodeName.substring(0, colonPos);
550                 localName = nodeName.substring(colonPos + 1, nodeName.length());
551             } else {
552                 prefix = null;
553                 localName = nodeName;
554             }
555             return new String JavaDoc[] {prefix, localName};
556         }
557
558
559         /**
560          * End processing of given node
561          *
562          * @param node Node we just finished processing
563          */

564         protected void endNode(Node JavaDoc node) throws org.xml.sax.SAXException JavaDoc {
565
566             switch (node.getNodeType()) {
567                 case Node.DOCUMENT_NODE:
568                     break;
569
570                 case Node.ELEMENT_NODE:
571                     contentHandler.endElement(currentElementInfo.namespaceURI,
572                             currentElementInfo.localName, currentElementInfo.qName);
573
574                     // generate endPrefixMapping events if needed
575
if (currentElementInfo.namespaceDeclarations != null && currentElementInfo.namespaceDeclarations.size() > 0) {
576                         Iterator JavaDoc namespaceIt = currentElementInfo.namespaceDeclarations.entrySet().iterator();
577                         while (namespaceIt.hasNext()) {
578                             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) namespaceIt.next();
579                             contentHandler.endPrefixMapping((String JavaDoc) entry.getKey());
580                             //System.out.println("ending prefix mapping " + (String) entry.getKey());
581
}
582                     }
583
584                     currentElementInfo = currentElementInfo.parent;
585                     break;
586                 case Node.CDATA_SECTION_NODE:
587                     break;
588                 case Node.ENTITY_REFERENCE_NODE:
589                     {
590                         EntityReference JavaDoc eref = (EntityReference JavaDoc) node;
591
592                         if (lexicalHandler != null) {
593                             lexicalHandler.endEntity(eref.getNodeName());
594                         }
595                     }
596                     break;
597                 default :
598             }
599         }
600
601         public static class ElementInfo {
602             public String JavaDoc localName;
603             public String JavaDoc namespaceURI;
604             public String JavaDoc qName;
605             public Map JavaDoc namespaceDeclarations = null;
606             public ElementInfo parent;
607
608             public ElementInfo(ElementInfo parent) {
609                 this.parent = parent;
610             }
611
612             /**
613              * Declare a new namespace prefix on this element, possibly overriding
614              * an existing one.
615              */

616             public void put(String JavaDoc prefix, String JavaDoc namespaceURI) {
617                 if (namespaceDeclarations == null)
618                     namespaceDeclarations = new HashMap JavaDoc();
619                 namespaceDeclarations.put(prefix, namespaceURI);
620             }
621
622             /**
623              * Finds a prefix declared on this element.
624              */

625             public String JavaDoc getPrefix(String JavaDoc namespaceURI) {
626                 if (namespaceDeclarations == null || namespaceDeclarations.size() == 0)
627                     return null;
628                 // note: there could be more than one prefix for the same namespaceURI, but
629
// we return the first found one.
630
Iterator JavaDoc it = namespaceDeclarations.entrySet().iterator();
631                 while (it.hasNext()) {
632                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
633                     if (entry.getValue().equals(namespaceURI))
634                         return (String JavaDoc) entry.getKey();
635                 }
636                 return null;
637             }
638
639             /**
640              * Finds a namespace URI declared on this element.
641              */

642             public String JavaDoc getNamespaceURI(String JavaDoc prefix) {
643                 if (namespaceDeclarations == null || namespaceDeclarations.size() == 0)
644                     return null;
645
646                 return (String JavaDoc) namespaceDeclarations.get(prefix);
647             }
648
649             /**
650              * Finds a prefix declaration on this element or containing elements.
651              */

652             public String JavaDoc findPrefix(String JavaDoc namespaceURI) {
653                 if (namespaceDeclarations != null && namespaceDeclarations.size() != 0) {
654                     String JavaDoc prefix = getPrefix(namespaceURI);
655                     if (prefix != null) {
656                         return prefix;
657                     }
658                 }
659                 if (parent != null) {
660                     return parent.findPrefix(namespaceURI);
661                 } else {
662                     return null;
663                 }
664             }
665
666             /**
667              * Finds a namespace declaration on this element or containing elements.
668              */

669             public String JavaDoc findNamespaceURI(String JavaDoc prefix) {
670                 if (namespaceDeclarations != null && namespaceDeclarations.size() != 0) {
671                     String JavaDoc uri = (String JavaDoc) namespaceDeclarations.get(prefix);
672                     if (uri != null) {
673                         return uri;
674                     }
675                 }
676                 if (parent != null)
677                     return parent.findNamespaceURI(prefix);
678                 else
679                     return null;
680             }
681         }
682     }
683
684     /**
685      * The <code>DefaultDOMStreamer</code> is a utility class that will generate SAX
686      * events from a W3C DOM Document.
687      *
688      * @author <a HREF="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
689      * @author <a HREF="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
690      * (Apache Software Foundation)
691      */

692     public static class DefaultDOMStreamer extends AbstractXMLProducer {
693
694         /** The private transformer for this instance */
695         protected Transformer JavaDoc transformer;
696
697         /**
698          * Start the production of SAX events.
699          */

700         public void stream(Node JavaDoc node)
701         throws SAXException JavaDoc {
702             if (this.transformer == null) {
703                 try {
704                     this.transformer = factory.newTransformer();
705                 } catch (TransformerConfigurationException JavaDoc e) {
706                     throw new SAXException JavaDoc(e);
707                 }
708             }
709             DOMSource JavaDoc source = new DOMSource JavaDoc(node);
710
711             ContentHandler JavaDoc handler;
712             if (node.getNodeType() == Node.DOCUMENT_NODE) {
713                 // Pass all SAX events
714
handler = contentHandler;
715             } else {
716                 // Strip start/endDocument
717
handler = new EmbeddedXMLPipe(contentHandler);
718             }
719
720             SAXResult JavaDoc result = new SAXResult JavaDoc(handler);
721             result.setLexicalHandler(lexicalHandler);
722
723             try {
724                 transformer.transform(source, result);
725             } catch (TransformerException JavaDoc e) {
726                 throw new SAXException JavaDoc(e);
727             }
728         }
729     }
730 }
731
Popular Tags