KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > dom > DOMSender


1 package net.sf.saxon.dom;
2 import net.sf.saxon.event.PipelineConfiguration;
3 import net.sf.saxon.event.Receiver;
4 import net.sf.saxon.event.SaxonLocator;
5 import net.sf.saxon.om.Name;
6 import net.sf.saxon.om.NamePool;
7 import net.sf.saxon.style.StandardNames;
8 import net.sf.saxon.trans.DynamicError;
9 import net.sf.saxon.trans.XPathException;
10 import org.w3c.dom.*;
11 import org.xml.sax.helpers.AttributesImpl JavaDoc;
12 import org.xml.sax.helpers.NamespaceSupport JavaDoc;
13
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16
17 /**
18 * DOMSender.java: pseudo-SAX driver for a DOM source document.
19 * This class takes an existing
20 * DOM Document and walks around it in a depth-first traversal,
21 * calling a Receiver to process the nodes as it does so
22 */

23
24 public class DOMSender implements SaxonLocator {
25     private Receiver receiver;
26     private PipelineConfiguration pipe;
27
28     private NamespaceSupport JavaDoc nsSupport = new NamespaceSupport JavaDoc();
29     private AttributesImpl JavaDoc attlist = new AttributesImpl JavaDoc();
30     private String JavaDoc[] parts = new String JavaDoc[3];
31     private String JavaDoc[] elparts = new String JavaDoc[3];
32     private HashMap JavaDoc nsDeclarations = new HashMap JavaDoc(10);
33     protected Node root = null;
34     protected String JavaDoc systemId;
35
36     /**
37      * Set the pipeline configuration
38      */

39
40     public void setPipelineConfiguration(PipelineConfiguration pipe) {
41         this.pipe = pipe;
42     }
43
44     /**
45     * Set the receiver.
46     * @param receiver The object to receive content events.
47     */

48
49     public void setReceiver (Receiver receiver) {
50         this.receiver = receiver;
51     }
52
53     /**
54     * Set the DOM Document that will be walked
55     */

56
57     public void setStartNode(Node start) {
58         root = start;
59     }
60
61     /**
62     * Set the systemId of the source document (which will also be
63     * used for the destination)
64     */

65
66     public void setSystemId(String JavaDoc systemId) {
67         this.systemId = systemId;
68     }
69
70     /**
71     * Walk a document (traversing the nodes depth first)
72     * @exception net.sf.saxon.trans.XPathException On any error in the document
73     */

74
75     public void send() throws XPathException {
76         if (root==null) {
77             throw new DynamicError("DOMSender: no start node defined");
78         }
79         if (receiver==null) {
80             throw new DynamicError("DOMSender: no receiver defined");
81         }
82
83         receiver.setSystemId(systemId);
84         pipe.setLocationProvider(this);
85         receiver.setPipelineConfiguration(pipe);
86
87         receiver.open();
88         if (root.getNodeType() == Node.ELEMENT_NODE) {
89             sendElement((Element)root);
90         } else {
91             // walk the root node
92
receiver.startDocument(0);
93             walkNode(root);
94             receiver.endDocument();
95         }
96         receiver.close();
97     }
98
99     /**
100      * Walk a document starting from a particular element node. This has to make
101      * sure that all the namespace declarations in scope for the element are
102      * treated as if they were namespace declarations on the element itself.
103      */

104
105     private void sendElement(Element startNode) throws XPathException {
106         Element node = startNode;
107         NamedNodeMap topAtts = gatherNamespaces(node, false);
108         while (true) {
109             gatherNamespaces(node, true);
110             Node parent = node.getParentNode();
111             if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
112                 node = (Element)parent;
113             } else {
114                 break;
115             }
116         }
117         outputElement(startNode, topAtts);
118     }
119
120   /**
121     * Walk an element of a document (traversing the children depth first)
122     * @param node The DOM Element object to walk
123     * @exception net.sf.saxon.trans.XPathException On any error in the document
124     *
125     */

126
127     private void walkNode (Node node) throws XPathException {
128         if (node.hasChildNodes()) {
129             NodeList nit = node.getChildNodes();
130             for (int i=0; i<nit.getLength(); i++) {
131                 Node child = nit.item(i);
132                 switch (child.getNodeType()) {
133                     case Node.DOCUMENT_NODE:
134                         break; // should not happen
135
case Node.ELEMENT_NODE:
136                         Element element = (Element)child;
137                         NamedNodeMap atts = gatherNamespaces(element, false);
138
139                         outputElement(element, atts);
140
141                         nsSupport.popContext();
142                         break;
143                     case Node.ATTRIBUTE_NODE: // have already dealt with attributes
144
break;
145                     case Node.PROCESSING_INSTRUCTION_NODE:
146                         receiver.processingInstruction(
147                             ((ProcessingInstruction)child).getTarget(),
148                             ((ProcessingInstruction)child).getData(),
149                                 0, 0);
150                         break;
151                     case Node.COMMENT_NODE: {
152                         String JavaDoc text = ((Comment)child).getData();
153                         if (text!=null) {
154                             receiver.comment(text, 0, 0);
155                         }
156                         break;
157                     }
158                     case Node.TEXT_NODE:
159                     case Node.CDATA_SECTION_NODE: {
160                         String JavaDoc text = ((CharacterData)child).getData();
161                         if (text!=null) {
162                             receiver.characters(text, 0, 0);
163                         }
164                         break;
165                     }
166                     case Node.ENTITY_REFERENCE_NODE:
167                         walkNode(child);
168                         break;
169                     default:
170                         break; // should not happen
171
}
172             }
173         }
174
175     }
176
177     private void outputElement(Element element, NamedNodeMap atts) throws XPathException {
178         String JavaDoc[] elparts2 = nsSupport.processName(element.getTagName(), elparts, false);
179         if (elparts2==null) {
180               throw new DynamicError("Undeclared namespace in " + element.getTagName());
181         }
182         String JavaDoc uri = elparts2[0];
183         String JavaDoc local = elparts2[1];
184         String JavaDoc prefix = Name.getPrefix(elparts2[2]);
185
186         NamePool namePool = pipe.getConfiguration().getNamePool();
187         int nameCode = namePool.allocate(prefix, uri, local);
188
189         receiver.startElement(nameCode, StandardNames.XDT_UNTYPED, 0, 0);
190         for (Iterator JavaDoc iter = nsDeclarations.keySet().iterator(); iter.hasNext();) {
191             String JavaDoc nsprefix = (String JavaDoc)iter.next();
192             String JavaDoc nsuri = (String JavaDoc)nsDeclarations.get(nsprefix);
193             receiver.namespace(namePool.allocateNamespaceCode(nsprefix, nsuri), 0);
194         }
195
196         if (atts != null) {
197             for (int a2=0; a2<atts.getLength(); a2++) {
198                 Attr att = (Attr)atts.item(a2);
199                 String JavaDoc attname = att.getName();
200                 if (!attname.equals("xmlns") && !attname.startsWith("xmlns:")) {
201                     //System.err.println("Processing attribute " + attname);
202
String JavaDoc[] parts2 = nsSupport.processName(attname, parts, true);
203                     if (parts2==null) {
204                           throw new DynamicError("Undeclared namespace in " + attname);
205                     }
206                     String JavaDoc atturi = parts2[0];
207                     String JavaDoc attlocal = parts2[1];
208                     String JavaDoc attprefix = Name.getPrefix(parts2[2]);
209
210                     int attCode = namePool.allocate(attprefix, atturi, attlocal);
211
212                     receiver.attribute(attCode, StandardNames.XDT_UNTYPED_ATOMIC, att.getValue(), 0, 0);
213                 }
214             }
215         }
216         receiver.startContent();
217
218         walkNode(element);
219
220         receiver.endElement();
221     }
222
223     /**
224      * Collect all the namespace attributes in scope for a given element
225      * @param element
226      * @param cumulative
227      * @return
228      */

229
230     private NamedNodeMap gatherNamespaces(Element element, boolean cumulative) {
231         if (!cumulative) {
232             nsSupport.pushContext();
233             attlist.clear();
234             nsDeclarations.clear();
235         }
236
237         // we can't rely on namespace declaration attributes being present -
238
// there may be undeclared namespace prefixes. (If the DOM is a Saxon
239
// tree, there will be no namespace declaration attributes.) So we
240
// declare all namespaces encountered, to be on the safe side.
241

242         try {
243             String JavaDoc prefix = element.getPrefix();
244             String JavaDoc uri = element.getNamespaceURI();
245             if (prefix==null) prefix="";
246             if (uri==null) uri="";
247             //System.err.println("Implicit Namespace: " + prefix + "=" + uri);
248
if (nsDeclarations.get(prefix)==null) {
249                 nsSupport.declarePrefix(prefix, uri);
250                 nsDeclarations.put(prefix, uri);
251             }
252         } catch (Throwable JavaDoc err) {
253             // it must be a level 1 DOM
254
}
255
256         NamedNodeMap atts = element.getAttributes();
257
258         // Apparently the Oracle DOM returns null if there are no attributes:
259
if (atts == null) {
260             return null;
261         }
262         for (int a1=0; a1<atts.getLength(); a1++) {
263             Attr att = (Attr)atts.item(a1);
264             String JavaDoc attname = att.getName();
265             if (attname.equals("xmlns")) {
266                 //System.err.println("Default namespace: " + att.getValue());
267
if (nsDeclarations.get("")==null) {
268                     String JavaDoc uri = att.getValue();
269                     nsSupport.declarePrefix("", uri);
270                     nsDeclarations.put("", uri);
271                 }
272             } else if (attname.startsWith("xmlns:")) {
273                 //System.err.println("Namespace: " + attname.substring(6) + "=" + att.getValue());
274
String JavaDoc prefix = attname.substring(6);
275                 if (nsDeclarations.get(prefix)==null) {
276                     String JavaDoc uri = att.getValue();
277                     nsSupport.declarePrefix(prefix, uri);
278                     nsDeclarations.put(prefix, uri);
279                 }
280             } else if (attname.indexOf(':')>=0) {
281                 try {
282                     String JavaDoc prefix = att.getPrefix();
283                     String JavaDoc uri = att.getNamespaceURI();
284                     //System.err.println("Implicit Namespace: " + prefix + "=" + uri);
285
if (nsDeclarations.get(prefix)==null) {
286                         nsSupport.declarePrefix(prefix, uri);
287                         //contentHandler.startPrefixMapping(prefix, uri);
288
nsDeclarations.put(prefix, uri);
289                     }
290                 } catch (Throwable JavaDoc err) {
291                     // it must be a level 1 DOM
292
}
293             }
294         }
295         return atts;
296     }
297
298     // Implement the SAX Locator interface. This is needed to pass the base URI of nodes
299
// to the receiver. We don't attempt to preserve the original base URI of each individual
300
// node as it is copied, only the base URI of the document as a whole.
301

302     public int getColumnNumber() {
303         return -1;
304     }
305
306     public int getLineNumber() {
307         return -1;
308     }
309
310     public String JavaDoc getPublicId() {
311         return null;
312     }
313
314     public String JavaDoc getSystemId() {
315         return systemId;
316     }
317
318     public String JavaDoc getSystemId(int locationId) {
319         return getSystemId();
320     }
321
322     public int getLineNumber(int locationId) {
323         return getLineNumber();
324     }
325
326 // public static void main(String[] args) throws Exception {
327
// Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
328
// Element keyInfo = doc.createElement("plughole");
329
// StringWriter sw = new StringWriter();
330
// Transformer transformer = TransformerFactory.newInstance().newTransformer();
331
// transformer.transform(new DOMSource(keyInfo), new StreamResult(sw));
332
// sw.close();
333
// System.out.println(sw.toString());
334
//
335
// }
336

337 }
338 //
339
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
340
// you may not use this file except in compliance with the License. You may obtain a copy of the
341
// License at http://www.mozilla.org/MPL/
342
//
343
// Software distributed under the License is distributed on an "AS IS" basis,
344
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
345
// See the License for the specific language governing rights and limitations under the License.
346
//
347
// The Original Code is: all this file.
348
//
349
// The Initial Developer of the Original Code is Michael H. Kay.
350
//
351
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
352
//
353
// Contributor(s): none.
354
//
355
Popular Tags