KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > tree > ElementWithAttributes


1 package net.sf.saxon.tree;
2 import net.sf.saxon.event.LocationCopier;
3 import net.sf.saxon.event.Receiver;
4 import net.sf.saxon.om.*;
5 import net.sf.saxon.trans.XPathException;
6 import net.sf.saxon.type.Type;
7 import net.sf.saxon.style.StandardNames;
8
9 import java.util.HashSet JavaDoc;
10 import java.util.Iterator JavaDoc;
11 import java.util.Set JavaDoc;
12
13 /**
14   * A node in the XML parse tree representing an XML element.<P>
15   * This class is an implementation of NodeInfo
16   * @author Michael H. Kay
17   * @version 8 August 2000: separated from ElementImpl
18   */

19
20 // The name of the element and its attributes are now namespace-resolved by the
21
// parser. However, this class retains the ability to do namespace resolution for other
22
// names, for example variable and template names in a stylesheet.
23

24 public class ElementWithAttributes extends ElementImpl {
25
26     protected AttributeCollection attributeList; // this excludes namespace attributes
27
protected int[] namespaceList = null; // list of namespace codes
28
// note that this namespace list includes only the namespaces actually defined on
29
// this element, not those inherited from outer elements.
30

31
32     /**
33     * Initialise a new ElementWithAttributes with an element name and attribute list
34     * @param nameCode The element name, with namespaces resolved
35     * @param atts The attribute list, after namespace processing
36     * @param parent The parent node
37     */

38
39     public void initialise(int nameCode, AttributeCollectionImpl atts, NodeInfo parent,
40                             String JavaDoc baseURI, int lineNumber, int sequenceNumber) {
41         this.nameCode = nameCode;
42         this.attributeList = atts;
43         this.parent = (ParentNodeImpl)parent;
44         this.sequence = sequenceNumber;
45         this.root = (DocumentImpl)parent.getDocumentRoot();
46         root.setLineNumber(sequenceNumber, lineNumber);
47         root.setSystemId(sequenceNumber, baseURI);
48     }
49
50     /**
51     * Set the namespace declarations for the element
52     */

53
54     public void setNamespaceDeclarations(int[] namespaces, int namespacesUsed) {
55         namespaceList = new int[namespacesUsed];
56         System.arraycopy(namespaces, 0, namespaceList, 0, namespacesUsed);
57     }
58
59     /**
60      * Get the namespace URI corresponding to a given prefix. Return null
61      * if the prefix is not in scope.
62      *
63      * @param prefix the namespace prefix. May be the zero-length string, indicating
64      * that there is no prefix. This indicates either the default namespace or the
65      * null namespace, depending on the value of useDefault.
66      * @param useDefault true if the default namespace is to be used when the
67      * prefix is "". If false, the method returns "" when the prefix is "".
68      * @return the uri for the namespace, or null if the prefix is not in scope.
69      * The "null namespace" is represented by the pseudo-URI "".
70      */

71
72     public String JavaDoc getURIForPrefix(String JavaDoc prefix, boolean useDefault) {
73         if (prefix.equals("xml")) {
74             return NamespaceConstant.XML;
75         }
76         if (prefix.equals("") && !useDefault) {
77             return "";
78         }
79
80         NamePool pool = getNamePool();
81         int prefixCode = pool.getCodeForPrefix(prefix);
82         if (prefixCode==-1) {
83             return null;
84         }
85         try {
86             short uriCode = getURICodeForPrefixCode(prefixCode);
87             return pool.getURIFromURICode(uriCode);
88         } catch (NamespaceException e) {
89             return null;
90         }
91     }
92
93     /**
94      * Get an iterator over all the prefixes declared in this namespace context. This will include
95      * the default namespace (prefix="") and the XML namespace where appropriate
96      */

97
98     public Iterator JavaDoc iteratePrefixes() {
99         Set JavaDoc inScope = new HashSet JavaDoc(10);
100         Set JavaDoc outOfScope = new HashSet JavaDoc(10);
101         inScope.add("");
102         inScope.add("xml");
103         gatherNamespacePrefixes(getNamePool(), inScope, outOfScope);
104         return inScope.iterator();
105     }
106
107     /**
108     * Search the NamespaceList for a given prefix, returning the corresponding URI.
109     * @param prefix The prefix to be matched. To find the default namespace, supply ""
110     * @return The URI code corresponding to this namespace. If it is an unnamed default namespace,
111     * return Namespace.NULL_CODE.
112     * @throws NamespaceException if the prefix has not been declared on this NamespaceList.
113     */

114
115     public short getURICodeForPrefix(String JavaDoc prefix) throws NamespaceException {
116         if (prefix.equals("xml")) return NamespaceConstant.XML_CODE;
117
118         NamePool pool = getNamePool();
119         int prefixCode = pool.getCodeForPrefix(prefix);
120         if (prefixCode==-1) {
121             throw new NamespaceException(prefix);
122         }
123         return getURICodeForPrefixCode(prefixCode);
124     }
125
126     private short getURICodeForPrefixCode(int prefixCode) throws NamespaceException {
127         if (namespaceList!=null) {
128             for (int i=0; i<namespaceList.length; i++) {
129                 if ((namespaceList[i]>>16) == prefixCode) {
130                     return (short)(namespaceList[i] & 0xffff);
131                 }
132             }
133         }
134         NodeInfo next = parent;
135         while (true) {
136             if (next.getNodeKind()==Type.DOCUMENT) {
137                 // prefixCode==0 represents the empty namespace prefix ""
138
if (prefixCode==0) return NamespaceConstant.NULL_CODE;
139                 throw new NamespaceException(getNamePool().getPrefixFromNamespaceCode(prefixCode<<16));
140             } else if (next instanceof ElementWithAttributes) {
141                 return ((ElementWithAttributes)next).getURICodeForPrefixCode(prefixCode);
142             } else {
143                 next = next.getParent();
144             }
145         }
146     }
147
148     /**
149     * Search the NamespaceList for a given URI, returning the corresponding prefix.
150     * @param uri The URI to be matched.
151     * @return The prefix corresponding to this URI. If not found, return null. If there is
152     * more than one prefix matching the URI, the first one found is returned. If the URI matches
153     * the default namespace, return an empty string.
154     */

155
156     public String JavaDoc getPrefixForURI(String JavaDoc uri) {
157         if (uri.equals(NamespaceConstant.XML)) return "xml";
158
159         NamePool pool = getNamePool();
160         int uriCode = pool.getCodeForURI(uri);
161         if (uriCode<0) return null;
162         return getPrefixForURICode(uriCode);
163     }
164
165     private String JavaDoc getPrefixForURICode(int code) {
166         if (namespaceList!=null) {
167             for (int i=0; i<namespaceList.length; i++) {
168                 if ((namespaceList[i] & 0xffff) == code) {
169                     return getNamePool().getPrefixFromNamespaceCode(namespaceList[i]);
170                 }
171             }
172         }
173         NodeInfo next = parent;
174         while (true) {
175             if (next instanceof DocumentInfo) {
176                 return null;
177             } else if (next instanceof ElementWithAttributes) {
178                 return ((ElementWithAttributes)next).getPrefixForURICode(code);
179             } else {
180                 next = next.getParent();
181             }
182         }
183     }
184
185     private void gatherNamespacePrefixes(NamePool pool, Set JavaDoc inScope, Set JavaDoc outOfScope) {
186         if (namespaceList!=null) {
187             for (int i=0; i<namespaceList.length; i++) {
188                 int nscode = namespaceList[i];
189                 String JavaDoc prefix = pool.getPrefixFromNamespaceCode(nscode);
190                 if ((nscode & 0xffff) == 0) {
191                     // this is an undeclaration
192
outOfScope.add(prefix);
193                 } else if (!outOfScope.contains(prefix)) {
194                     inScope.add(prefix);
195                     outOfScope.add(prefix);
196                 }
197             }
198         }
199
200         // now add the namespaces defined on the ancestor nodes
201

202         NodeInfo parent = getParent();
203         while (parent != null) {
204             if (parent instanceof ElementWithAttributes) {
205                 ((ElementWithAttributes)parent).gatherNamespacePrefixes(pool, inScope, outOfScope);
206             }
207         }
208     }
209
210
211     /**
212     * Output all namespace nodes associated with this element.
213     * @param out The relevant outputter
214      */

215
216     public void sendNamespaceDeclarations(Receiver out, boolean includeAncestors) throws XPathException {
217
218         if (namespaceList!=null) {
219             for (int i=0; i<namespaceList.length; i++) {
220                 out.namespace(namespaceList[i], 0);
221             }
222         }
223
224         // now add the namespaces defined on the ancestor nodes. We rely on the outputter
225
// to eliminate multiple declarations of the same prefix
226

227         if (includeAncestors) {
228             if (parent.getNodeKind()!=Type.DOCUMENT) {
229                 parent.sendNamespaceDeclarations(out, true);
230             }
231         }
232     }
233
234     /**
235      * Get all namespace undeclarations and undeclarations defined on this element.
236      *
237      * @param buffer If this is non-null, and the result array fits in this buffer, then the result
238      * may overwrite the contents of this array, to avoid the cost of allocating a new array on the heap.
239      * @return An array of integers representing the namespace declarations and undeclarations present on
240      * this element. For a node other than an element, return null. Otherwise, the returned array is a
241      * sequence of namespace codes, whose meaning may be interpreted by reference to the name pool. The
242      * top half word of each namespace code represents the prefix, the bottom half represents the URI.
243      * If the bottom half is zero, then this is a namespace undeclaration rather than a declaration.
244      * The XML namespace is never included in the list. If the supplied array is larger than required,
245      * then the first unused entry will be set to -1.
246      * <p/>
247      * <p>For a node other than an element, the method returns null.</p>
248      */

249
250     public int[] getDeclaredNamespaces(int[] buffer) {
251         return namespaceList;
252     }
253
254     /**
255     * Get the list of in-scope namespaces for this element as an array of
256     * namespace codes. (Used by LiteralResultElement)
257     */

258
259     public int[] getInScopeNamespaceCodes() {
260         return new NamespaceIterator(this, null).getInScopeNamespaceCodes();
261     }
262
263     /**
264     * Get the attribute list for this element.
265     * @return The attribute list. This will not include any
266     * namespace attributes. The attribute names will be in expanded form, with prefixes
267     * replaced by URIs
268     */

269
270     public AttributeCollection getAttributeList() {
271         return attributeList;
272     }
273
274     /**
275     * Get the value of a given attribute of this node
276     * @param fingerprint The fingerprint of the attribute name
277     * @return the attribute value if it exists or null if not
278     */

279
280     public String JavaDoc getAttributeValue(int fingerprint) {
281         return attributeList.getValueByFingerprint(fingerprint);
282     }
283
284     /**
285     * Copy this node to a given outputter (supporting xsl:copy-of)
286     * @param out The outputter
287     * @param whichNamespaces indicates which namespaces should be output: all, none, or local
288     * namespaces only (those not declared on the parent element)
289     */

290
291     public void copy(Receiver out, int whichNamespaces, boolean copyAnnotations, int locationId) throws XPathException {
292
293         int typeCode = (copyAnnotations ? getTypeAnnotation() : -1);
294         if (locationId == 0 && out instanceof LocationCopier) {
295             out.setSystemId(getBaseURI());
296             ((LocationCopier)out).setLineNumber(getLineNumber());
297         }
298         out.startElement(getNameCode(), typeCode, locationId, 0);
299
300         // output the namespaces
301

302         if (whichNamespaces != NO_NAMESPACES) {
303             sendNamespaceDeclarations(out, whichNamespaces==ALL_NAMESPACES);
304         }
305
306         // output the attributes
307

308         for (int i=0; i<attributeList.getLength(); i++) {
309             out.attribute(attributeList.getNameCode(i), StandardNames.XDT_UNTYPED_ATOMIC,
310                                attributeList.getValue(i), 0, 0);
311         }
312
313         out.startContent();
314
315         // output the children
316

317         int childNamespaces = (whichNamespaces==NO_NAMESPACES ? NO_NAMESPACES : LOCAL_NAMESPACES);
318         NodeImpl next = (NodeImpl)getFirstChild();
319         while (next!=null) {
320             next.copy(out, childNamespaces, copyAnnotations, locationId);
321             next = (NodeImpl)next.getNextSibling();
322         }
323
324         out.endElement();
325     }
326
327 }
328
329 //
330
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
331
// you may not use this file except in compliance with the License. You may obtain a copy of the
332
// License at http://www.mozilla.org/MPL/
333
//
334
// Software distributed under the License is distributed on an "AS IS" basis,
335
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
336
// See the License for the specific language governing rights and limitations under the License.
337
//
338
// The Original Code is: all this file.
339
//
340
// The Initial Developer of the Original Code is Michael H. Kay.
341
//
342
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
343
//
344
// Contributor(s): none.
345
//
346
Popular Tags