KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > output > NamespaceEmitter


1 package com.icl.saxon.output;
2 import com.icl.saxon.*;
3 //import com.icl.saxon.om.Name;
4
import com.icl.saxon.om.Namespace;
5 import com.icl.saxon.om.NamePool;
6 import org.xml.sax.Attributes JavaDoc;
7 import java.io.*;
8 import java.util.*;
9 import javax.xml.transform.TransformerException JavaDoc;
10
11 /**
12   * NamespaceEmitter is a ProxyEmitter responsible for removing duplicate namespace
13   * declarations. It also ensures that an xmlns="" undeclaration is output when
14   * necessary.
15   */

16   
17 public class NamespaceEmitter extends ProxyEmitter
18 {
19     protected NamePool namePool;
20     protected int nscodeXML;
21     protected int nscodeNull;
22
23     // We keep track of namespaces to avoid outputting duplicate declarations. The namespaces
24
// vector holds a list of all namespaces currently declared (organised as pairs of entries,
25
// prefix followed by URI). The stack contains an entry for each element currently open; the
26
// value on the stack is an Integer giving the size of the namespaces vector on entry to that
27
// element.
28

29     private int[] namespaces = new int[30]; // all namespace codes currently declared
30
private int namespacesSize = 0; // all namespaces currently declared
31
private int[] namespaceStack = new int[100];
32     private int nsStackTop = 0;
33
34     
35     /**
36     * Set the name pool to be used for all name codes
37     */

38     
39     public void setNamePool(NamePool pool) {
40                 //pool.diagnosticDump();
41
namePool = pool;
42         nscodeXML = pool.getNamespaceCode("xml", Namespace.XML);
43         nscodeNull = pool.getNamespaceCode("", "");
44         super.setNamePool(pool);
45     }
46     
47
48     /**
49     * startElement. This call removes redundant namespace declarations, and
50     * possibly adds an xmlns="" undeclaration.
51     */

52
53     public void startElement(int nameCode, Attributes JavaDoc attList,
54                              int[] namespaceCodes, int nrOfCodes) throws TransformerException JavaDoc {
55                 
56                 // System.err.println("NSEmitter startElement nameCode=" + nameCode);
57
// for (int i=0; i<nrOfCodes; i++) {
58
// System.err.println(" NS " + namespaceCodes[i]);
59
// }
60

61         // Create an array to hold the unique namespaces
62

63         int[] uniqueNamespaces = new int[namespaceCodes.length+1];
64         int uniqueCount = 0;
65
66         // Ensure that the element namespace is output
67

68         int elementNamespace = namePool.allocateNamespaceCode(nameCode);
69         if (isNeeded(elementNamespace)) {
70             addToStack(elementNamespace);
71             uniqueNamespaces[uniqueCount++] = elementNamespace;
72         }
73
74         // Now de-duplicate the supplied list of namespaces
75

76         for (int n=0; n<nrOfCodes; n++) {
77             int nscode = namespaceCodes[n];
78             if (isNeeded(nscode)) {
79                 addToStack(nscode);
80                 uniqueNamespaces[uniqueCount++] = nscode;
81             }
82         }
83
84         // remember how many namespaces there were so we can unwind the stack later
85

86         if (nsStackTop>=namespaceStack.length) {
87             int[] newstack = new int[nsStackTop*2];
88             System.arraycopy(namespaceStack, 0, newstack, 0, nsStackTop);
89             namespaceStack = newstack;
90         }
91
92         namespaceStack[nsStackTop++] = uniqueCount;
93
94         // finally, pass the namespace on to the underlying Emitter
95
super.startElement(nameCode, attList, uniqueNamespaces, uniqueCount);
96     }
97
98     /**
99     * Determine whether a namespace declaration is needed
100     */

101     
102     private boolean isNeeded(int nscode) {
103         if (nscode==nscodeXML) {
104                 // Ignore the XML namespace
105
return false;
106         }
107
108         for (int i=namespacesSize-1; i>=0; i--) {
109             if (namespaces[i]==nscode) {
110                 // it's a duplicate so we don't need it
111
return false;
112             }
113             if ((namespaces[i]>>16) == (nscode>>16)) {
114                 // same prefix, different URI, so we do need it
115
return true;
116             }
117         }
118         return (nscode != nscodeNull);
119     }
120             
121     /**
122     * Add a namespace declaration to the stack
123     */

124
125     private void addToStack(int nscode) {
126         // expand the stack if necessary
127
if (namespacesSize+1 >= namespaces.length) {
128             int[] newlist = new int[namespacesSize*2];
129             System.arraycopy(namespaces, 0, newlist, 0, namespacesSize);
130             namespaces = newlist;
131         }
132         namespaces[namespacesSize++] = nscode;
133     }
134                 
135
136     /**
137     * endElement: Discard the namespaces declared on this element.
138     */

139
140
141     public void endElement (int nameCode) throws TransformerException JavaDoc
142     {
143         if (nsStackTop-- == 0) {
144             throw new TransformerException JavaDoc("Attempt to output end tag with no matching start tag");
145         }
146         
147         int nscount = namespaceStack[nsStackTop];
148         namespacesSize -= nscount;
149         
150         super.endElement(nameCode);
151
152     }
153 }
154
155 //
156
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
157
// you may not use this file except in compliance with the License. You may obtain a copy of the
158
// License at http://www.mozilla.org/MPL/
159
//
160
// Software distributed under the License is distributed on an "AS IS" basis,
161
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
162
// See the License for the specific language governing rights and limitations under the License.
163
//
164
// The Original Code is: all this file.
165
//
166
// The Initial Developer of the Original Code is
167
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
168
//
169
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
170
//
171
// Contributor(s): none.
172
//
173
Popular Tags